Skip to content

Repository files navigation

rm-sc

Service Commander for IBM i, reimplemented in RPGLE.

A drop-in replacement for Service Commander (sc), which is written in Java. Same YAML service definitions, same command surface, same output format — without the JVM cold start, and without forking db2util for every liveness query.

Library RMSC — object names cannot contain hyphens
Test library RMSCT
Build TOBimakei build
Tests IBM i Testing extension + iRPGUnit

Status

Working. 144 test cases, 578 assertions across 11 suites. check, list and groups are byte-identical to the Java implementation.

Module Does
SCYAML Reads the YAML subset service definitions use
SCDEF Types a definition and applies upstream's defaults
SCDIRS Resolves the definition search path
SCCOLL Discovery, groups, dependency order with cycle detection
SCQRY Liveness and reporting queries, as embedded SQL
SCNET Port status via the TCP/IP list API, ~540x faster than the SQL service
SCJOB Active job lookup via QUSLJOB, ~125ms per call faster than the SQL service
SCOUT Output formatting, byte-identical to upstream
SCLOG Log file location
SCLAUNCH Starting, stopping, environment assembly
SCEXEC Status determination and the twelve operations
SCMAIN Command line parsing and dispatch
SCAPI Bound-call API for ILE callers

Usable three ways: the scr shell wrapper, the SC CL command, and — for an ILE caller that wants values rather than text to parse — the bound-call API in QPROTOSRC/SCAPI_D.RPGLEINC.

Why

sc was assumed to be slow for two reasons:

  1. JVM cold start on every invocation.
  2. db2util fork-per-queryQueryUtils.java runs each of its 11 SQL statements by spawning a process and opening a fresh database connection.

An ILE program removes both — and measured, that bought only about 20%, with list actually slower than Java. Neither assumption survived contact with a stopwatch: the JVM start is smaller than expected, and the fork is not what dominates a liveness query. The IBM i SQL table functions are. Filtering NETSTAT_INFO to one port cost the same as returning every row of it, while PASE netstat returned the same data, process fork included, five times faster.

What actually made RMSC fast was replacing those table functions with the system APIs underneath them — QtocLstNetCnn for port status, QUSLJOB for job lookup. scr check now runs in about 1.6s against Java's ~3.4s.

The measurements, including the ones that disproved the original premise, are in docs/performance.md.

Compatibility

check output is byte-for-byte identical to upstream. This is deliberate and load-bearing: sc's output is a de facto interface, and consumers parse it by column position.

  RUNNING            | webproxy (Web Proxy)
Element Rule
Leading exactly two spaces
Status columns 3–20, left-justified, padded to width 18
Separator space at column 21, `
Name column 24 to the space before (
Description between ( and the last )
Trailing one space after )

Equivalently ' ' + %left(status:18) + ' | ' + name + ' (' + desc + ') '.

Colour is suppressed when stdout is not a TTY, for the same reason — ANSI escapes would land inside the status columns and corrupt them.

fixtures/ holds reference captures in this layout for the format tests.

Autostart at IPL

RMSC does not hook into STRTCPSVR. Starting services at IPL stays with the Java implementation, deliberately.

The *SC TCP server hardcodes the path to the Java sc inside a QSYS-owned program, so repointing it means either modifying a program the package installed — which a package update would silently revert — or registering a parallel server special value. Both are possible; neither earns its risk. RMSC's speed advantage is worth nothing at IPL, where the work runs once, unattended, with nobody waiting, and the failure mode is a service not coming back after a restart.

Scope

Full parity with upstream except cluster mode and nginx cluster.conf generation, and therefore reload, which is cluster-only upstream. Running nginx as an ordinary managed service is unaffected — that is a normal service definition, not cluster mode.

Dependencies

Requires rmtools 2.0.7 or later, a general-purpose RPGLE helper library (service program RMBASE), consumed two ways with different lifetimes:

  • Copybooks — needed at compile time only, via INCDIR.
  • Modules — bound by copy, so RMSC carries no runtime dependency on the RMTOOLS library and no job calling it needs RMTOOLS on its library list. See docs/tobi-binding.md.

Why 2.0.7 specifically. Before it, PATH_BASENAME_t was varchar(128), so a service whose file name exceeded 127 characters lost its name entirely — PATH_name truncated the name, lost the extension off the end, failed to find the dot and returned an empty string through a MONITOR. Two such services then collided, and one vanished from check.

Built against 2.0.6 the suites go red in about ten places across SCDEF, SCCOLL and SCLAUNCH, and nothing in the failure text names rmtools as the cause — the markers that used to say so were flipped to ordinary assertions when 2.0.7 landed. If you see that cluster, check the version first.

rmtools is not currently publicly available, so this repository cannot be built by third parties as it stands. Publishing it is intended but not yet straightforward.

Licence

MIT.

Service Commander itself is a separate project, licensed Apache-2.0. This is an independent reimplementation, not a fork or derivative of its source.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages