🚨 Oracle not porting Rdb to x86 and EOL on Itanium 12/2027 🚨
Technical Capabilities
Having trouble finding what you need?
Get in touch with us, so we can answer your specific questions directly.
Get In Touch

VX/ACMS - Application Control and Management System

Overview

VX/ACMS is a native C++20 reimplementation of VSI ACMS (Application Control and Management System) for Linux. It provides source-compatible task execution for migrated OpenVMS applications: existing TDF / GDF / ADF sources compile through the ADU, existing COBOL and C step procedures run unchanged, and existing calls to ACMS$ services resolve against the same signatures and status codes as on VMS.

VX/ACMS targets the single-server deployment model used by the majority of production ACMS estates. Multi-node clustering and DDTM/XA are v2 scope items.

<!-- Webflow embed (min). Source: vx-acms-page-technical/acms-tech-body-embed-dark.html → python3 website/embeds/minify_webflow_embed.py … --> <div class="s7-tech-embed" data-vxacmsd-body-embed="1" data-technical-mega-embed="1" lang="en"><h2 id="components">Component map</h2><p> VX/ACMS preserves the ACMS component model verbatim. Each VMS process class has an exact Linux counterpart with the same responsibilities; only the IPC substrate changes (POSIX shared memory and UNIX-domain sockets instead of VMS global sections and DECnet links). </p><div class="table-wrapper"><table><thead><tr><th>VMS process</th><th>Linux binary</th><th>Role</th><th>Status</th></tr></thead><tbody><tr><td>ACC</td><td><code>acmsd</code></td><td>Root daemon. Owns the SQLite control / audit / queue databases; spawns child processes; listens on the operator socket (<code>/run/acms/operator.sock</code>).</td><td><span class="ac-live">live</span></td></tr><tr><td>EXC</td><td><code>acms-exc</code></td><td>Per-application task interpreter. Drives IF / WHILE / REPEAT / GOTO / ATOMIC / EXCHANGE / PROCESSING steps; loads task <code>.so</code> files via <code>dlopen</code>; manages workspace pool.</td><td><span class="ac-live">live</span></td></tr><tr><td>SP</td><td><code>acms-sp</code></td><td>Procedure server pool. Loads server group <code>.so</code> files; dispatches PROCESSING CALL steps from EXC via UDS; maintains server process pool sizing.</td><td><span class="ac-live">live</span></td></tr><tr><td>CP</td><td><code>acms-cp</code></td><td>Per-submitter FORMS$ / menu process. Bridges terminal I/O through VSI DECforms <code>libvxdf*</code> on Linux. Handles EXCHANGE steps bound to forms.</td><td><span class="ac-v1">v1 soon</span></td></tr><tr><td>QTI</td><td><code>acms-qti</code></td><td>Queued task initiator. Drains the SQLite-backed task queue; submits deferred tasks to EXC; honours priority ordering.</td><td><span class="ac-v1">v1 soon</span></td></tr><tr><td>ATL</td><td><code>acms-atl</code></td><td>Audit trail logger. Receives structured log events from all other components via the SWL library; writes to the audit database.</td><td><span class="ac-live">live</span></td></tr><tr><td>SWL</td><td><code>liblogswl</code></td><td>In-process event log library. Wraps all structured logging; consumed by ACC / EXC / SP / QTI / ATL.</td><td><span class="ac-live">live</span></td></tr><tr><td>SI (agent)</td><td><code>libacms_si.so</code></td><td>Agent-callable surface. Provides <code>ACMS$CALL</code>, <code>ACMS$SIGN_IN</code>, and 10 other implemented services. Linked by submitter programs.</td><td><span class="ac-live">live (12 svc)</span></td></tr><tr><td>ADU</td><td><code>adu</code> / <code>adu_compile</code></td><td>Application Definition Utility. Parses TDF / GDF / ADF / MDF; resolves CDD$ records; emits C++; compiles to <code>.so</code>.</td><td><span class="ac-live">live (MDF v1)</span></td></tr></tbody></table></div><div class="callout"><strong>No RR server in v1.</strong> The Remote Request (RR) inter-node server is a v2 item. All inter-process communication in v1 is on a single Linux host via UNIX-domain sockets and shared memory. </div><h2 id="workspaces">Workspace model</h2><p> Workspaces are the shared-memory records that flow between a submitter, the EXC task interpreter, and SP procedure servers. VX/ACMS maps the VMS global section model onto POSIX <code>shm_open</code> / <code>mmap</code>; the layout of each workspace is determined by its CDD record and is verified at install time by matching a <code>layout_hash</code>. </p><h6>Workspace lifetimes</h6><div class="table-wrapper"><table><thead><tr><th>Lifetime</th><th>VMS equivalent</th><th>Scope</th></tr></thead><tbody><tr><td><code>TASK</code></td><td>Task workspace</td><td>Allocated at task call entry; released at <code>EXIT TASK</code> or exception unwind.</td></tr><tr><td><code>USER</code></td><td>Per-submitter workspace</td><td>Lives for the duration of the submitter's ACMS session (sign-in to sign-out).</td></tr><tr><td><code>GROUP</code></td><td>Group workspace</td><td>Shared across all tasks in the same application group; lifetime = application runtime.</td></tr><tr><td><code>SYSTEM</code></td><td>System workspace</td><td>Shared system-wide. Includes the three ACMS-maintained system workspaces (<code>ACMS$SELECTION_STRING</code>, <code>ACMS$PROCESSING_STATUS</code>, <code>ACMS$TASK_INFORMATION</code>).</td></tr></tbody></table></div><h6>Workspace handle</h6><p>Every workspace in VX/ACMS is identified by a handle passed through the CBOR IPC frames:</p> <pre>{ shm_id: uint32 // POSIX shm name index offset: uint64 // byte offset within the mapping length: uint32 // record byte length version: uint16 // layout_hash low word (checked at first access) }</pre> <h6>CDD integration</h6><p> Record layouts are authoritative in the CDD database (<code>banking.cdd.db</code>) built by <code>vxcdd --add</code>. Both the ADU compiler and the COBOL/C compilers consume CDD views — no hand-maintained struct duplicates. The <code>layout_hash</code> is a deterministic hash of the flattened CDD field list; a mismatch between the task <code>.so</code> and the server <code>.so</code> causes a hard install-time error. </p><div class="callout warn"><strong>TASK ARGUMENTS copy boundary.</strong> When a submitter passes workspaces to EXC as <code>TASK ARGUMENTS</code>, the contents are copied across the submitter/EXC process split. All other workspace access (EXC ↔ SP) is zero-copy shared memory. </div><h6>System workspaces</h6><div class="table-wrapper"><table><thead><tr><th>Name</th><th>Content</th></tr></thead><tbody><tr><td><code>ACMS$SELECTION_STRING</code></td><td>Task selector passed by the submitter at <code>ACMS$CALL</code> time.</td></tr><tr><td><code>ACMS$PROCESSING_STATUS</code></td><td>Status returned from the most recent PROCESSING step.</td></tr><tr><td><code>ACMS$TASK_INFORMATION</code></td><td>Submitter identity, task name, call flags; populated by EXC at task entry.</td></tr></tbody></table></div><h2 id="tdl">TDL — Task Definition Language</h2><p> TDL is the language you use to define ACMS tasks, task groups, and applications. The ADU compiler processes four TDL file types: TDF (tasks), GDF (groups / server definitions), ADF (applications), and MDF (menus). All four compile unchanged through VX/ACMS. </p><h6>Task Definition File (TDF)</h6><p>A TDF defines one or more tasks. Each task declares its workspaces, task arguments, and a BLOCK of steps. A minimal task:</p> <pre><span class="kw">REPLACE TASK</span> FUNDS_TRANSFER <span class="kw">WORKSPACES ARE</span> ACCOUNT_WKSP, TRANSFER_WKSP, AUDIT_WKSP; <span class="kw">TASK ARGUMENTS ARE</span> ACCOUNT_WKSP <span class="kw">WITH ACCESS</span> MODIFY, AUDIT_WKSP <span class="kw">WITH ACCESS</span> WRITE; <span class="kw">BLOCK</span> <span class="kw">EXCEPTION HANDLER</span> <span class="kw">MOVE</span> <span class="str">"FAILED"</span> <span class="kw">TO</span> AUDIT_WKSP.MSG; <span class="kw">EXIT TASK</span>; <span class="kw">PROCESSING CALL</span> READ_ACCOUNT <span class="kw">USING</span> ACCOUNT_WKSP; <span class="kw">IF</span> ACCOUNT_WKSP.BALANCE &lt; TRANSFER_WKSP.AMOUNT <span class="kw">THEN</span> <span class="kw">MOVE</span> <span class="str">"NSF"</span> <span class="kw">TO</span> AUDIT_WKSP.MSG; <span class="kw">EXIT TASK</span>; <span class="kw">END IF</span>; <span class="kw">PROCESSING CALL</span> DEBIT_ACCOUNT <span class="kw">USING</span> ACCOUNT_WKSP, TRANSFER_WKSP; <span class="kw">END BLOCK</span>; <span class="kw">END DEFINITION</span>;</pre> <h6>Step types</h6><div class="table-wrapper"><table><thead><tr><th>Step</th><th>Purpose</th></tr></thead><tbody><tr><td><code>PROCESSING CALL name USING wksp, …</code></td><td>Dispatch to a server procedure in an SP process. The named procedure must appear in the GDF.</td></tr><tr><td><code>EXCHANGE USING wksp WRITING form …</code></td><td>Submit a FORMS$ exchange step; data flows through a CP process to the terminal.</td></tr><tr><td><code>ATOMIC BEGIN … END ATOMIC</code></td><td>Begin a SQLite-backed ATOMIC bracket (DDTM shape preserved). All enclosed steps are within one transaction context.</td></tr><tr><td><code>GET ERROR MESSAGE</code></td><td>Copy the current ACMS exception text into a workspace field.</td></tr><tr><td><code>MOVE value TO wksp.field</code></td><td>Assign a literal or workspace field to another workspace field inside EXC (no server dispatch).</td></tr><tr><td><code>IF … THEN … ELSE … END IF</code></td><td>Conditional based on workspace field comparison.</td></tr><tr><td><code>WHILE condition DO … END WHILE</code></td><td>Loop while condition holds.</td></tr><tr><td><code>REPEAT … END REPEAT</code></td><td>Unconditional loop; terminated by <code>EXIT LOOP</code>.</td></tr><tr><td><code>GOTO label</code></td><td>Unconditional branch to a labelled step within the same BLOCK.</td></tr><tr><td><code>EXIT TASK</code></td><td>Terminate the task normally.</td></tr></tbody></table></div><h6>Group Definition File (GDF)</h6><p>A GDF defines a server group: which server image (.so) to load, which procedures it exports, and lifecycle hooks:</p> <pre><span class="kw">REPLACE SERVER GROUP</span> BANKING_SERVERS <span class="kw">PROCEDURE SERVER IMAGE IS</span> <span class="str">"/opt/acms/servers/banking_servers.so"</span>; <span class="kw">INITIALIZATION PROCEDURE IS</span> BANKING_INIT; <span class="kw">TERMINATION PROCEDURE IS</span> BANKING_TERM; <span class="kw">CANCEL PROCEDURE IS</span> BANKING_CANCEL; <span class="kw">PROCEDURES ARE</span> READ_ACCOUNT, DEBIT_ACCOUNT, LOG_AUDIT; <span class="kw">END DEFINITION</span>;</pre> <h6>Application Definition File (ADF)</h6><p>An ADF registers tasks and server groups under a named ACMS application. It maps task selectors (used at <code>ACMS$CALL</code> time) to TDF-defined tasks and GDF-defined server groups:</p> <pre><span class="kw">REPLACE APPLICATION</span> BANKING <span class="kw">TASKS ARE</span> FUNDS_TRANSFER <span class="kw">USING TASK GROUP</span> BANKING_TASKS; <span class="kw">SERVER GROUPS ARE</span> BANKING_SERVERS; <span class="kw">END DEFINITION</span>;</pre> <h6>TDL keyword reference</h6><div class="kw-grid"><div>ACCESS</div><div>ADF</div><div>AND</div><div>APPLICATION</div><div>ATOMIC</div><div>BACKUP</div><div>BEGIN</div><div>BLOCK</div><div>CALL</div><div>CANCEL</div><div>CLEAR</div><div>DEFINE</div><div>DELETE</div><div>DO</div><div>ELSE</div><div>END</div><div>EXCEPTION</div><div>EXCHANGE</div><div>EXIT</div><div>FOR</div><div>FROM</div><div>GDF</div><div>GET</div><div>GOTO</div><div>GROUP</div><div>HANDLER</div><div>IF</div><div>IMAGE</div><div>IN</div><div>INITIALIZATION</div><div>IS</div><div>LOOP</div><div>MDF</div><div>MESSAGE</div><div>MODIFY</div><div>MOVE</div><div>NOT</div><div>ON</div><div>OR</div><div>PROCEDURE</div><div>PROCESSING</div><div>READ</div><div>REPEAT</div><div>REPLACE</div><div>SERVER</div><div>TASK</div><div>TDF</div><div>TERMINATION</div><div>THEN</div><div>TO</div><div>USING</div><div>WHILE</div><div>WITH</div><div>WORKSPACES</div><div>WRITE</div></div><h2 id="services">ACMS$ services</h2><p> Submitter programs link against <code>libacms_si.so</code> and call ACMS$ services to sign in, submit tasks, and sign out. VX/ACMS implements the 12 services used across production estates; the full VMS-compatible signature and status code set is preserved. </p><div class="table-wrapper"><table><thead><tr><th>Service</th><th>Purpose</th><th>Status</th></tr></thead><tbody><tr><td><code>ACMS$SIGN_IN</code></td><td>Authenticate the submitter and open an ACMS session. Validates against the PAM stack (or the internal rights store). Returns a session handle.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>ACMS$SIGN_OUT</code></td><td>Terminate the submitter's ACMS session and release all USER-lifetime workspaces.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>ACMS$CALL</code></td><td>Submit a task by application name and task selector. Blocks (or returns immediately with <code>ACMS$_PENDING</code> if non-blocking) until the task completes.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>ACMS$START_CALL</code></td><td>Asynchronous task submission. Pairs with <code>ACMS$WAIT_CALL</code> for the completion rendezvous.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>ACMS$WAIT_CALL</code></td><td>Block until a previously <code>ACMS$START_CALL</code>-submitted task completes.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>ACMS$CANCEL_CALL</code></td><td>Cancel an outstanding <code>ACMS$START_CALL</code> submission before it has been dispatched by EXC.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>ACMS$RAISE_STEP_EXCEPTION</code></td><td>Raise an exception from inside a server step procedure. The EXC EXCEPTION HANDLER fires at the nearest enclosing BLOCK.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>ACMS$SET_SELECTION_STRING</code></td><td>Pre-populate the <code>ACMS$SELECTION_STRING</code> system workspace before a <code>ACMS$CALL</code>.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>ACMS$GET_TASK_INFO</code></td><td>Read the current task's name, submitter identity, and call flags from <code>ACMS$TASK_INFORMATION</code>.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>ACMS$EXCHANGE_IO</code></td><td>Perform a forms-exchange I/O step from a server procedure (advanced use). Requires CP process.</td><td><span class="ac-v1">v1 soon (CP)</span></td></tr><tr><td><code>ACMS$QUEUE_TASK</code></td><td>Enqueue a task for deferred execution by QTI. Returns immediately; task runs when QTI dispatches it.</td><td><span class="ac-v1">surface live, QTI v1</span></td></tr><tr><td><code>ACMS$GET_ERROR_MESSAGE</code></td><td>Retrieve the text of the most recent ACMS exception. Corresponds to the <code>GET ERROR MESSAGE</code> TDL step when called from a server procedure.</td><td><span class="ac-live">live</span></td></tr></tbody></table></div><div class="callout"><strong>Status codes.</strong> VX/ACMS uses the same 32-bit ACMS status codes as VMS — <code>ACMS_NORMAL</code> (1), <code>ACMS$_NOSUCHAPP</code>, <code>ACMS$_STEP_ERR</code>, etc. A full table of status codes is available in Appendix A of the Programmer's Reference Manual. </div><h6>Calling ACMS$CALL from C</h6> <pre><span class="cmt">/* Minimal ACMS$CALL from C — funds transfer */</span> #include &lt;acms_si.h&gt; acms_session_t sess; acms_status_t rc; <span class="cmt">/* sign in */</span> rc = ACMS$SIGN_IN(<span class="str">"operator"</span>, &amp;sess); if (rc != ACMS_NORMAL) exit(1); <span class="cmt">/* populate TASK ARGUMENTS workspaces via shm handle */</span> memcpy(ws_account.shm_ptr, &amp;account_rec, sizeof(account_rec)); memcpy(ws_transfer.shm_ptr, &amp;transfer_rec, sizeof(transfer_rec)); <span class="cmt">/* call task */</span> rc = ACMS$CALL(&amp;sess, <span class="str">"BANKING"</span>, <span class="str">"FUNDS_TRANSFER"</span>, ws_array, 2, 0); if (rc != ACMS_NORMAL) handle_error(rc); ACMS$SIGN_OUT(&amp;sess);</pre> <h2 id="server-programming">Server programming</h2><p> Step procedures are compiled into server group <code>.so</code> files and loaded by the SP process via <code>dlopen</code>. VX/ACMS preserves the VMS server module ABI so that existing COBOL and C procedure source compiles and runs without modification. </p><h6>Server module ABI (C / C++)</h6><p>Each server group <code>.so</code> must export an <code>acms_server_module_v1</code> struct:</p> <pre><span class="kw">typedef struct</span> { uint32_t version; <span class="cmt">/* = ACMS_SERVER_MODULE_VERSION (1) */</span> const char *group_name; <span class="cmt">/* must match GDF SERVER GROUP name */</span> acms_proc_entry_t *procedures; <span class="cmt">/* null-terminated array */</span> acms_vfn_t on_init; <span class="cmt">/* INITIALIZATION PROCEDURE — may be NULL */</span> acms_vfn_t on_term; <span class="cmt">/* TERMINATION PROCEDURE — may be NULL */</span> acms_vfn_t on_cancel; <span class="cmt">/* CANCEL PROCEDURE — may be NULL */</span> } acms_server_module_v1;</pre> <p>Each procedure entry maps a name string to a function pointer:</p> <pre><span class="kw">typedef struct</span> { const char *name; <span class="cmt">/* must match GDF PROCEDURES ARE name */</span> acms_proc_fn_t fn; <span class="cmt">/* unsigned int fn(WKSP *a, WKSP *b, …) */</span> } acms_proc_entry_t; <span class="cmt">/* Procedure signature: one pointer per workspace declared USING */</span> <span class="kw">unsigned int</span> READ_ACCOUNT(ACCOUNT_WKSP_t *acct) { <span class="cmt">/* read account record — field access via struct layout */</span> if (acct-&gt;balance &lt; 0) <span class="kw">return</span> ACMS$_INSUFFICIENT_FUNDS; <span class="kw">return</span> ACMS_NORMAL; }</pre> <h6>COBOL step procedures</h6><p>COBOL procedures use the VMS-shape signature: workspace records appear as <code>BY REFERENCE</code> arguments in the <code>PROCEDURE DIVISION USING</code> clause, and the return status is conveyed through <code>RETURN-CODE</code> (not a function return value):</p> <pre><span class="kw">IDENTIFICATION DIVISION.</span> PROGRAM-ID. READ-ACCOUNT. <span class="kw">DATA DIVISION.</span> WORKING-STORAGE SECTION. <span class="kw">LINKAGE SECTION.</span> 01 ACCOUNT-WKSP. 05 ACCOUNT-ID PIC X(16). 05 BALANCE PIC S9(12)V99 COMP-3. 05 STATUS-MSG PIC X(40). <span class="kw">PROCEDURE DIVISION USING</span> ACCOUNT-WKSP. EXEC SQL SELECT BALANCE INTO :ACCOUNT-WKSP.BALANCE FROM ACCOUNTS WHERE ID = :ACCOUNT-WKSP.ACCOUNT-ID END-EXEC. IF SQLCODE &lt;&gt; 0 MOVE <span class="str">"NOT FOUND"</span> TO ACCOUNT-WKSP.STATUS-MSG MOVE ACMS-STEP-ERROR TO RETURN-CODE ELSE MOVE ACMS-NORMAL TO RETURN-CODE END-IF. STOP RUN.</pre> <div class="callout"><strong>layout_hash enforcement.</strong> The <code>layout_hash</code> in the workspace handle must match the hash compiled into the server <code>.so</code>. A mismatch is caught at install time by <code>acmsctl install</code> — not at runtime. Recompile both the task and server <code>.so</code> after any CDD record change. </div><h6>Exception handling from server code</h6><p> Call <code>ACMS$RAISE_STEP_EXCEPTION</code> to propagate a step-level error back to the EXC EXCEPTION HANDLER without using a C++ exception or a non-zero return value directly: </p> <pre><span class="kw">unsigned int</span> DEBIT_ACCOUNT(ACCOUNT_WKSP_t *acct, TRANSFER_WKSP_t *xfr) { <span class="kw">if</span> (xfr-&gt;amount &gt; acct-&gt;balance) { ACMS$RAISE_STEP_EXCEPTION(ACMS$_INSUFFICIENT_FUNDS, <span class="str">"Balance too low"</span>); <span class="kw">return</span> ACMS_NORMAL; <span class="cmt">/* control never reaches here */</span> } acct-&gt;balance -= xfr-&gt;amount; <span class="kw">return</span> ACMS_NORMAL; }</pre> <h2 id="build-pipeline">Build pipeline</h2><p> The ADU (Application Definition Utility) converts TDL sources to native Linux shared objects through a four-step pipeline. All steps are exposed through the <code>adu_compile</code> command-line tool. </p><h6>Pipeline steps</h6><div class="table-wrapper"><table><thead><tr><th>Step</th><th>Command</th><th>Input</th><th>Output</th></tr></thead><tbody><tr><td>1. CDD compile</td><td><code>vxcdd --add &lt;name&gt;.cdo</code></td><td>CDD object definition (<code>.cdo</code>)</td><td>CDD database (<code>*.cdd.db</code>)</td></tr><tr><td>2. GDF compile</td><td><code>adu_compile server.gdf --cdd *.cdd.db</code></td><td>Group definition file + CDD database</td><td><code>server_group.cpp</code> → <code>server_group.so</code></td></tr><tr><td>3. TDF compile</td><td><code>adu_compile task.tdf --gdf server.gdf --compile</code></td><td>Task definition file + GDF</td><td><code>task_module.cpp</code> → <code>task.so</code></td></tr><tr><td>4. Install</td><td><code>acmsctl install application &lt;APP&gt;</code></td><td>ADF + compiled <code>.so</code> files</td><td>Application registered in <code>control.db</code>; EXC/SP notified.</td></tr></tbody></table></div><h6>adu_compile flags</h6><div class="table-wrapper"><table><thead><tr><th>Flag</th><th>Purpose</th></tr></thead><tbody><tr><td><code>--cdd &lt;path&gt;</code></td><td>Path to the CDD database (required for workspace resolution).</td></tr><tr><td><code>--gdf &lt;path&gt;</code></td><td>Path to the compiled GDF (required for TDF step resolution).</td></tr><tr><td><code>--compile</code></td><td>Invoke the system C++ compiler on the generated <code>.cpp</code> and link the <code>.so</code>.</td></tr><tr><td><code>--output-dir &lt;dir&gt;</code></td><td>Write generated files to this directory (default: same as input).</td></tr><tr><td><code>--cxx &lt;compiler&gt;</code></td><td>C++ compiler binary (default: <code>g++</code>).</td></tr><tr><td><code>--cxxflags &lt;flags&gt;</code></td><td>Additional flags forwarded to the C++ compiler.</td></tr><tr><td><code>--verbose</code></td><td>Print resolver and emitter trace to stderr.</td></tr><tr><td><code>--dry-run</code></td><td>Parse and resolve; do not emit C++ or compile.</td></tr></tbody></table></div><h6>Full build example</h6> <pre><span class="cmt"># 1 — compile the CDD record repository</span> vxcdd --add banking.cdo <span class="cmt"># 2 — compile the server group</span> adu_compile banking_servers.gdf \ --cdd banking.cdd.db \ --compile \ --output-dir build/ <span class="cmt"># 3 — compile all task definitions</span> adu_compile funds_transfer.tdf enquiry.tdf audit_report.tdf \ --gdf banking_servers.gdf \ --cdd banking.cdd.db \ --compile \ --output-dir build/ <span class="cmt"># 4 — install the application</span> acmsctl install application BANKING \ --adf banking.adf \ --task-dir build/ \ --server-dir build/</pre> <h6>Incremental rebuild</h6><p> Re-run only the steps for the files you changed. If you modify a CDD record, you must recompile both the task <code>.so</code> and the server <code>.so</code> that reference that workspace — the <code>layout_hash</code> check at install time will catch any mismatch. Use <code>acmsctl reload application BANKING</code> to hot-reload an updated application without restarting <code>acmsd</code>. </p><div class="callout"><strong>Generated C++ is first-class source.</strong> Check <code>build/*.cpp</code> into version control alongside your TDF sources. A <code>git diff</code> of the generated files tells you precisely what semantic changes an ADU version bump or TDF edit produced. </div><h2 id="quickref">Quick reference</h2><h6>TDF step summary</h6><div class="table-wrapper"><table><thead><tr><th>Step</th><th>Syntax (abbreviated)</th><th>EXC action</th></tr></thead><tbody><tr><td>PROCESSING CALL</td><td><code>PROCESSING CALL proc USING wksp, …</code></td><td>Dispatch to SP; workspace handles passed by reference.</td></tr><tr><td>EXCHANGE</td><td><code>EXCHANGE USING wksp WRITING form TO wksp</code></td><td>Route through CP; FORMS$TRANSCEIVE called.</td></tr><tr><td>MOVE</td><td><code>MOVE "lit" TO wksp.field</code></td><td>Assign literal or field to workspace field in-process.</td></tr><tr><td>ATOMIC BEGIN</td><td><code>ATOMIC BEGIN … END ATOMIC</code></td><td>Open SQLite transaction bracket; all steps inside are atomic.</td></tr><tr><td>GET ERROR MESSAGE</td><td><code>GET ERROR MESSAGE INTO wksp.field</code></td><td>Copy current exception text to workspace.</td></tr><tr><td>IF / ELSE / END IF</td><td><code>IF wksp.field op value THEN … END IF</code></td><td>Conditional; evaluated by EXC interpreter.</td></tr><tr><td>WHILE / END WHILE</td><td><code>WHILE condition DO … END WHILE</code></td><td>Loop until condition false.</td></tr><tr><td>REPEAT / END REPEAT</td><td><code>REPEAT … EXIT LOOP … END REPEAT</code></td><td>Unconditional loop.</td></tr><tr><td>GOTO</td><td><code>GOTO label</code></td><td>Jump to labelled step within BLOCK.</td></tr><tr><td>EXIT TASK</td><td><code>EXIT TASK</code></td><td>Normal task termination.</td></tr><tr><td>EXCEPTION HANDLER</td><td><code>EXCEPTION HANDLER steps; END HANDLER</code></td><td>Catch any step exception in the enclosing BLOCK.</td></tr></tbody></table></div><h6>ACMS$ service quick reference</h6><div class="table-wrapper"><table><thead><tr><th>Service</th><th>One-liner</th><th>v1?</th></tr></thead><tbody><tr><td><code>ACMS$SIGN_IN</code></td><td>Open session; authenticate submitter.</td><td><span class="ac-live">✓</span></td></tr><tr><td><code>ACMS$SIGN_OUT</code></td><td>Close session; release USER workspaces.</td><td><span class="ac-live">✓</span></td></tr><tr><td><code>ACMS$CALL</code></td><td>Synchronous task submission.</td><td><span class="ac-live">✓</span></td></tr><tr><td><code>ACMS$START_CALL</code></td><td>Asynchronous task submission.</td><td><span class="ac-live">✓</span></td></tr><tr><td><code>ACMS$WAIT_CALL</code></td><td>Wait for async task completion.</td><td><span class="ac-live">✓</span></td></tr><tr><td><code>ACMS$CANCEL_CALL</code></td><td>Cancel pending async submission.</td><td><span class="ac-live">✓</span></td></tr><tr><td><code>ACMS$RAISE_STEP_EXCEPTION</code></td><td>Raise exception from server step.</td><td><span class="ac-live">✓</span></td></tr><tr><td><code>ACMS$SET_SELECTION_STRING</code></td><td>Pre-populate selection string workspace.</td><td><span class="ac-live">✓</span></td></tr><tr><td><code>ACMS$GET_TASK_INFO</code></td><td>Read task identity from system workspace.</td><td><span class="ac-live">✓</span></td></tr><tr><td><code>ACMS$EXCHANGE_IO</code></td><td>Forms exchange I/O from server code.</td><td><span class="ac-v1">v1 soon</span></td></tr><tr><td><code>ACMS$QUEUE_TASK</code></td><td>Enqueue task for deferred QTI dispatch.</td><td><span class="ac-v1">partial</span></td></tr><tr><td><code>ACMS$GET_ERROR_MESSAGE</code></td><td>Retrieve exception text string.</td><td><span class="ac-live">✓</span></td></tr></tbody></table></div><h6>acmsctl operator commands</h6><div class="table-wrapper"><table><thead><tr><th>Command</th><th>Purpose</th></tr></thead><tbody><tr><td><code>acmsctl install application APP --adf app.adf</code></td><td>Register application; verify layout hashes; notify EXC/SP.</td></tr><tr><td><code>acmsctl reload application APP</code></td><td>Hot-reload updated <code>.so</code> files without restarting acmsd.</td></tr><tr><td><code>acmsctl start application APP</code></td><td>Activate application for task submission.</td></tr><tr><td><code>acmsctl stop application APP</code></td><td>Quiesce application; drain in-flight tasks.</td></tr><tr><td><code>acmsctl call APP TASK</code></td><td>Test-call a task from the operator shell.</td></tr><tr><td><code>acmsctl show application APP</code></td><td>Print task list, server group status, active submitters.</td></tr><tr><td><code>acmsctl show statistics</code></td><td>Aggregate call counts, step latency percentiles, queue depth.</td></tr></tbody></table></div><h6>Key file paths (default layout)</h6><div class="table-wrapper"><table><thead><tr><th>Path</th><th>Contents</th></tr></thead><tbody><tr><td><code>/opt/acms/bin/</code></td><td><code>acmsd</code>, <code>acms-exc</code>, <code>acms-sp</code>, <code>acms-qti</code>, <code>acms-atl</code>, <code>acmsctl</code></td></tr><tr><td><code>/opt/acms/lib/</code></td><td><code>libacms_si.so</code>, <code>liblogswl.so</code></td></tr><tr><td><code>/opt/acms/applications/</code></td><td>Installed task and server <code>.so</code> files per application</td></tr><tr><td><code>/var/lib/acms/</code></td><td><code>control.db</code>, <code>audit.db</code>, <code>queue.db</code></td></tr><tr><td><code>/run/acms/</code></td><td>UNIX-domain sockets: <code>operator.sock</code>, per-EXC / per-SP sockets</td></tr><tr><td><code>/etc/acms/applications.conf</code></td><td>Boot-time application list; paths override <code>acmsctl install</code> defaults</td></tr></tbody></table></div></div>

Frequently Asked Questions

Curious about how Sector7 can facilitate your application migration? Explore our FAQs for expert insights.

No items found.

Transform Your Legacy Software Today!

Get In Touch
Unlock the potential of your legacy software with our expert migration services.