Oninit® Logwalker — Output Schema
Logwalker emits text. Every line is either a header line for one log record or an indented continuation line carrying that record's decoded body (or a hex dump of bytes the per-type decoder didn't handle). The Output Examples page links to verbatim sample output for each mode; this page documents the field shapes you'll see there.
HUMAN-mode header line
LSN <uniqid>:0x<low> xid=<N> <plain-English description>
| Field | Meaning |
|---|---|
| LSN <uniqid>:0x<low> | Canonical Informix LSN. The low half is the slotted-page encoding (page_idx « 12) | offset_in_page — not the raw chunk byte offset. The same value the loghdr's link field carries on the next record in the chain. |
| xid=<N> | Transaction id from the loghdr. Not unique across a log — the engine reuses xid values after a transaction completes. Pair with the BEGIN's LSN if you need a unique identifier; or use --group-by-xid which handles reuse explicitly. |
| plain-English description | Per-type sentence: INSERT into <db>.<table> (rowid 0x…, N bytes), BEGIN transaction (pid=N, started YYYY-MM-DD HH:MM:SS), CHALLOC — allocated N page(s) at chunk M page P, and so on. Partnums render as their catalog <db>.<table> names when the phase-1 catalog resolves them, else fall back to partition 0xN. |
Per-record-type body decoders
| Type code | Name | Decoded body fields |
|---|---|---|
| 0x0001 | BEGIN | begin_lsn_low + timestamp + uid + pid |
| 0x0002 | COMMIT | commit timestamp |
| 0x0004 | BEGCOM | commit timestamp (single-record begin+commit) |
| 0x0009 | CKPOINT | header only |
| 0x000d | ERASE | partnum |
| 0x0011 | UNIQID | partnum + next_serial |
| 0x001c | ADDITEM | parent_part + child_part + rowid + slot_len + 2 trailing int2 columns |
| 0x0020 | BLDCL | partnum + four numeric columns + table name (catalog-aware) |
| 0x0028 | HINSERT | partnum + rowid + rowlen (rowlen is an int2; the high bytes belong to a different field) |
| 0x0029 | HDELETE | partnum + rowid + rowlen |
| 0x002a | HUPBEF | partnum + rowid + rowlen |
| 0x002b | HUPAFT | partnum + rowid + rowlen |
| 0x0032 | PTEXTEND | partnum + n_pages + chunk:page |
| 0x0033 | CHALLOC | chunk + first_page + n_pages |
| 0x0034 | CHFREE | chunk + first_page + n_pages |
| 0x0076 | PTRUNCATE | partnum |
| 0x0077 | TRUNCATE | partnum |
Unknown record types render as 0x<HHHH> in the description slot and the full body hex-dumps to stdout, 16 bytes per line, indented eight spaces so the dump lines up under the header. The walker never stops on an unknown type — it always advances by the header's len field to the next record.
Schema-aware row decoding
With --decode-rows, HINSERT / HUPAFT / HUPBEF / HDELETE bodies decode as (col1=val1, col2=val2, …) against the phase-2 column map. Covered column types: SMALLINT, INTEGER, SERIAL, BIGINT, BIGSERIAL, INT8, SERIAL8, DATE (DATE 'YYYY-MM-DD'), CHAR / NCHAR (blank-trimmed, single-quote-escaped), VARCHAR / NVARCHAR, LVARCHAR, BOOLEAN. Other types (FLOAT, SMALLFLOAT, DECIMAL, DATETIME, INTERVAL, MONEY, BYTE, TEXT, BLOB) render as <type N:H bytes> placeholders so the rest of the row stays decodable.
Partial-row caveat: when a HUPBEF / HUPAFT records only the columns that changed (not the whole row), the decoded form looks like (col1=val1, …, col4=val4, …other columns NOT LOGGED) — the trailing marker is literal, not Logwalker shorthand. The engine genuinely didn't log the rest.
--compat onlog form
With --compat onlog, logwalker emits the legacy onlog -l shape: a one-line banner addr len type xid id link followed by one line per record in the same column order. Tail extras after the basic six columns match onlog -n output:
- BEGIN — MM/DD/YYYY HH:MM:SS <pid> <username> (username resolved from the body's uid via getpwuid())
- COMMIT / BEGCOM — MM/DD/YYYY HH:MM:SS
- HINSERT / HDELETE / HUPBEF / HUPAFT — <partnum_hex> <rowid_hex> <rowlen>
- UNIQID — <partnum_hex> <next_serial>
- ADDITEM — <parent> <child> <rowid> <slot_len> <extra1> <extra2>
- BLDCL — <partnum> <n1> <n2> <n3> <n4> <table_name>
- CHALLOC / CHFREE — <chunk:page> <n_pages>
- PTEXTEND — <partnum> <n_pages> <chunk:page>
- ERASE — <partnum>
- PTRUNCATE / TRUNCATE — <partnum> 0
Address style in --compat onlog is bare hex (no 0x prefix) to match the legacy column-1 display. Addresses are inflated by one pagesize per crossed chunk-page boundary so they agree with onlog's page_idx × 2×pagesize + offset_in_page scheme — HUMAN mode uses the same transform under the LSN low formatting, just rendered as 0x….
--group-by-xid framing
With --group-by-xid, every BEGIN gets a leading frame line:
--- TX <xid> BEGIN @ LSN <uniqid>:<low> ---
…every COMMIT / BEGCOM gets a trailing frame line:
--- TX <xid> COMMITTED @ LSN <uniqid>:<low> ---
…and when an xid value recurs (the engine has recycled it after a prior transaction completed), the new BEGIN line is tagged (xid REUSED):
--- TX 26 BEGIN @ LSN 302:0x278 (xid REUSED) ---
ROLLBACK frames close with --- TX <xid> ROLLED BACK @ LSN … --- rather than COMMITTED.
Residual-record caveat
Logwalker walks raw chunk bytes sequentially. When the engine recycles a log file, the new uniqid’s records overwrite the chunk pages but the engine doesn’t scrub the bytes — pages that the new uniqid hasn’t filled yet still carry bytes from the prior generation. Logwalker has no signal to skip those residual bytes, so the record count it surfaces for a partially-filled uniqid will diverge from onlog -n's view of the same uniqid (which filters by the per-page logserial stamp). Within any single transaction’s BEGIN → COMMIT chain the two tools agree record-for-record; the divergence is at the inter-transaction layer.