Join each IMS transaction and job step to the segments behind it
io.moderne.mainframe.ims.AnalyzeImsChainio.moderne.recipe:recipes-mainframeUsage
Run this recipe
This recipe has no required configuration options. Users of Moderne can run it via the Moderne CLI.
You will need to have configured the Moderne CLI on your machine before you can run the following command.
mod run . --recipe AnalyzeImsChain
If the recipe is not available locally, then you can install it using:
RELEASE resolves to the newest release and LATEST to the newest build of any kind, including snapshots. Either one lets mod config recipes upgrade pull in later versions without editing this command; a pinned version stays where you put it.
- RELEASE
- LATEST
- Pinned version
mod config recipes jar install io.moderne.recipe:recipes-mainframe:RELEASE
mod config recipes jar install io.moderne.recipe:recipes-mainframe:LATEST
mod config recipes jar install io.moderne.recipe:recipes-mainframe:0.1.0
Data tables
IMS segment access
io.moderne.mainframe.analysis.table.ImsSegmentAccessEvery DL/I call with the database it reaches, which the COBOL never names: the call gives a PCB and the PSB turns that into a database, and only then does the segment name mean something.
mod study . --last-recipe-run \
--data-table io.moderne.mainframe.analysis.table.ImsSegmentAccess
| Column | Description |
|---|---|
| Program | The program making the call. |
| Paragraph | The paragraph or section the call is in. |
| Interface | CBLTDLI, AIBTDLI, CEETDLI, PLITDLI or EXEC DLI. Which one it is decides how the PCB is named: by position in the entry list, by PCBNAME in the AIB, or by number among the database PCBs. |
| Function | The DL/I function, such as GU, GN, ISRT, REPL or DLET. |
| CRUD | CREATE, READ, UPDATE, DELETE, CHECKPOINT or SYSTEM, from the function. |
| PSB | The PSB the program runs under, empty where nothing says which one. A batch program's PSB is on the PARM of the region step; a message driven program's is the APPLCTN macro of the stage 1 deck. |
| PCB | The PCB as the PSB names it — its PCBNAME, else the PSB and the position, written CLMPSB02(3). |
| PCB position | The PCB's one-based position among the PSB's PCB statements, or zero where it did not resolve. This is not the mask: an I/O PCB is a mask and not a PCB statement. |
| Mask | The one-based position of the PCB in the program's entry list, or zero for a call that names its PCB rather than counting to it. |
| Reaches | SEGMENT for a database call, MESSAGE_QUEUE for the queue or the scratchpad, LOG for a checkpoint or restart, SEQUENTIAL for a GSAM record, UNRESOLVED where no PSB answered for the PCB. |
| Database | The IMS database the PCB opens, empty where the PCB is not a database one or did not resolve. This is the column nothing in the COBOL carries. |
| Index database | The secondary index the PCB's PROCSEQ walks the roots in, empty where it has none. A call through such a PCB reaches the database through the index. |
| Segments | The segments the call's search arguments name, space separated. A path call names several and reaches them all in the one call. |
| Source path | The program's file. |
| Line | The one-based line the call is written on. |
IMS chain
io.moderne.mainframe.analysis.table.ImsChainOne row per path from something that starts a program to a database it may reach: a transaction code or a job step, the program, the PSB it runs under, one PCB of that PSB, and the database and segments behind it.
mod study . --last-recipe-run \
--data-table io.moderne.mainframe.analysis.table.ImsChain
| Column | Description |
|---|---|
| Start kind | TRANSACTION where a message schedules the PSB, JOB_STEP where a region step runs it. |
| Start | The transaction code, or the job. |
| Step | The job step, empty for a transaction. |
| Program | The program the region loads, empty where nothing in the estate says which one. A batch region takes it on the PARM beside the PSB; a message region loads the module named for the PSB, so which program that module holds is the link-edit deck's to say. |
| Program path | The program's file, empty where it was not read here. |
| PSB | The PSB, which is what turns a PCB position into a database. |
| PSB path | The PSB's file, empty where no gen source for it was read. |
| PCB | The PCB as the PSB names it — its PCBNAME, else the PSB and the position. |
| PCB position | The PCB's one-based position among the PSB's PCB statements. |
| PCB type | DB for a database PCB and GSAM for a sequential one. Message PCBs get no row: they reach the terminal network rather than a database. |
| Processing options | The PROCOPT the PCB opens the database with, which is what says whether the path is a read or a write. |
| Database | The IMS database the PCB opens. |
| Database path | The DBD's file, empty where no gen source for it was read. |
| Index database | The secondary index named on PROCSEQ, empty where the PCB has none. |
| Sensitive segments | The segments the PSB lets the program see through this PCB, space separated. GSAM has none. |
| Segments | The segments the program's calls through this PCB actually name, space separated. Narrower than the sensitive list wherever a program is given more than it uses, and empty where the program was not read. |
IMS databases
io.moderne.mainframe.analysis.table.ImsDatabasesOne row per DBD: how it is organised, the DD names a job has to supply for it, and what it holds.
mod study . --last-recipe-run \
--data-table io.moderne.mainframe.analysis.table.ImsDatabases
| Column | Description |
|---|---|
| Database | The DBD name, which is what a PCB's DBDNAME and a stage 1 DATABASE macro name it by. |
| Organization | HDAM, HIDAM, HISAM, INDEX, GSAM or LOGICAL — the first operand of ACCESS, which says how a segment is found. |
| Access method | The operating system access method under it, VSAM or BSAM, from the second operand of ACCESS. |
| Randomizer | The RMNAME module an HDAM database hashes its root keys with, empty for every other organization. |
| DD names | The DD names the DATASET statements ask for, space separated. This is also an edge to every job step that runs against the database, since the step has to supply them. |
| Root segment | The segment with no parent, empty for GSAM, which has no segments at all. |
| Segments | How many segments the DBD defines. |
| Fields | How many FIELD statements it defines across those segments. |
| Record lengths | The RECORD lengths of a GSAM or HISAM data set group, space separated, empty where none is written. |
| References | The other databases this one names and why, written LOGICAL_PARENT CLMDBD02.POLROOT, space separated. A logical relationship and a secondary index are the only ways one DBD names another. |
| Source path | The gen source the DBD is written in. |
| Line | The one-based line of the DBD statement. |
IMS segments
io.moderne.mainframe.analysis.table.ImsSegmentsThe segment hierarchy of each DBD: the parent, the length, the sequence field and the fields with their offsets, which is the layout the copybook a program reads it into has to agree with.
mod study . --last-recipe-run \
--data-table io.moderne.mainframe.analysis.table.ImsSegments
| Column | Description |
|---|---|
| Database | The DBD the segment belongs to. |
| Segment | The segment name, which is what a search argument's first eight bytes carry. |
| Parent | The physical parent, empty for the root. |
| Level | How far down the hierarchy the segment sits, 1 for the root. |
| Bytes | The BYTES length, which is the length of the I/O area a program reads it into — unless the PCB is field sensitive, in which case the SENFLD list is. |
| Sequence field | The field the segment is keyed on, empty where it has none. |
| Sequence start | The one-based byte the sequence field starts at, zero where there is none. |
| Sequence length | How many bytes the sequence field is, zero where there is none. |
| Unique | Whether the sequence field is unique, which is what decides whether two occurrences can share a key. |
| Fields | Every FIELD of the segment, written CLMKEY 1(10) with a type where one is given, space separated and in source order. |
| Logical parent | The segment in another database this one is the logical child of, written CLMDBD02.POLROOT, empty where it is not one. |
| Logical children | The logical children pointed at from here, space separated. Written on the parent's side, which is the side a reader of the DBD sees first. |
| Secondary indexes | The indexes built over this segment, written CLMDBX01.CLMXSEG on CLMXADJ, space separated. The XDFLD says which field is indexed and the LCHILD says which database holds the index. |
| Source path | The gen source the segment is written in. |
| Line | The one-based line of the SEGM statement. |
IMS field-sensitive I/O areas
io.moderne.mainframe.analysis.table.ImsFieldSensitiveAreasWhat a field-sensitive PCB hands a program, against the copybook the program reads it with. Where a PCB carries SENFLDs the I/O area is not the segment: it holds those fields, at those offsets, and a program using the whole segment's layout reads every field after the first omission out of the wrong bytes.
mod study . --last-recipe-run \
--data-table io.moderne.mainframe.analysis.table.ImsFieldSensitiveAreas
| Column | Description |
|---|---|
| Program | The program making the call. |
| PSB | The PSB the program runs under. |
| PCB | The PCB as the PSB names it — its PCBNAME, else the PSB and the position, written CLMPSB02(2). |
| Segment | The segment the SENSEG names, which is the one the call asks for. |
| Sensitive fields | The SENFLDs in the order they build the area, each with the byte it starts at: CLMKEY 1 CLMPOL 11. A field of the segment that is not here is not in the area. |
| Expected bytes | How long the area is: the last SENFLD's start plus the length the DBD gives that field. Zero where a SENFLD names a field the DBD does not. |
| I/O area | The data item the call moves the segment into. |
| Copybook | The copybook that declares the I/O area, empty where the program declares it itself. |
| Copybook bytes | How many bytes that declaration describes, zero where it cannot be laid out. |
| Verdict | MATCH where the copybook is the length the SENFLDs build, DIFFERENT_LENGTH where it is not, UNKNOWN where one of the two lengths could not be worked out. |
| Source path | The program's file. |
| Line | The one-based line the call is written on. |
Findings
io.moderne.mainframe.analysis.table.FindingsEverything the mainframe analyses found wrong, ranked, with the evidence for each and the line it is on. Sort on priority.
mod study . --last-recipe-run \
--data-table io.moderne.mainframe.analysis.table.Findings
| Column | Description |
|---|---|
| Priority | 1 for CRITICAL down to 4 for LOW, so the table sorts. |
| Severity | CRITICAL for code that cannot do what it was written to do, HIGH for what will break a migration if not decided deliberately, MEDIUM for what is worth knowing first, LOW for cleanup. |
| Category | What kind of problem it is, which is what groups the report into sections: DEAD_RULE, UNREACHABLE_CODE, COPYBOOK_DRIFT, MIGRATION_BLOCKER, RANGE_PATHOLOGY, DEAD_DATA, COMPLEXITY, LAYOUT_DRIFT, IMS_PCB_MISMATCH, IMS_SEGMENT_NOT_SENSITIVE, IMS_IO_AREA_MISMATCH, MFS_MESSAGE_LENGTH, SCREEN_ITEM_UNREACHED, SCREEN_FIELD_UNREACHED, PARSE_FAILURE, UNDOCUMENTED, STALE_DOCUMENTATION, STALE_REFERENCE, UNENFORCED_BUILD_ORDER, UNSCHEDULED_JOB, AUTOCALL_RESOLVED_REFERENCE, UNRESOLVED_EXECUTION_PATH, INHERITED_SETTING, UNLOAD_NEEDS_REDESIGN, UNLOAD_ACCESS_MODE, UNLOAD_CONSISTENCY, UNLOAD_OUTPUT_WIRING, MIXED_SUBSTITUTION. |
| Program | The COBOL program, or the copybook where the finding is about one. |
| Summary | The finding in one sentence, written to be read on its own. |
| Evidence | Why this is claimed — the conditions that conflict, the two declarations that differ, the caller that made the paragraph unreachable. A finding nobody can check is a finding nobody will act on. |
| Where | The paragraph, section or data item the finding is in. |
| Source path | The file, so the finding can be opened. |
COBOL relationships
org.openrewrite.mainframe.cobol.table.CobolRelationshipsRelationships between different COBOL resources.
mod study . --last-recipe-run \
--data-table org.openrewrite.mainframe.cobol.table.CobolRelationships
| Column | Description |
|---|---|
| Dependent | The resource that defines the relationship. |
| Dependent type | The resource type of the resource that defines the relationship. |
| Action | The action that links the dependent and dependency. |
| Dependency | The resource that is exercised or linked to. |
| Dependency type | The resource type of the resource that is exercised or linked to. |
| Dependency missing | Indicates whether the dependency is a known resource. |
| Action metadata | Additional data about the action. |
| Dependent path | The source file the dependent's statement was written in, or null when the dependent is a name that has no source here. |
| Dependent line | The one-based line the dependent's statement was written on, or null when it has no source here. |
| Dependency path | The source file the dependency was written in, or null when the dependency is a name that has no source here, such as a vendor copybook. |
| Dependency line | The one-based line the dependency's statement was written on, or null when the dependency is a whole file rather than a statement within one. |
Source files that had results
org.openrewrite.table.SourcesFileResultsSource files that were modified by the recipe run.
mod study . --last-recipe-run \
--data-table org.openrewrite.table.SourcesFileResults
| Column | Description |
|---|---|
| Source path before the run | The source path of the file before the run. null when a source file was created during the run. |
| Source path after the run | A recipe may modify the source path. This is the path after the run. null when a source file was deleted during the run. |
| Parent of the recipe that made changes | In a hierarchical recipe, the parent of the recipe that made a change. Empty if this is the root of a hierarchy or if the recipe is not hierarchical at all. |
| Recipe that made changes | The specific recipe that made a change. |
| Estimated time saving | An estimated effort that a developer to fix manually instead of using this recipe, in unit of seconds. |
| Cycle | The recipe cycle in which the change was made. |
Source files that had search results
org.openrewrite.table.SearchResultsSearch results that were found during the recipe run.
mod study . --last-recipe-run \
--data-table org.openrewrite.table.SearchResults
| Column | Description |
|---|---|
| Source path of search result before the run | The source path of the file with the search result markers present. |
| Source path of search result after run the run | A recipe may modify the source path. This is the path after the run. null when a source file was deleted during the run. |
| Result | The trimmed printed tree of the LST element that the marker is attached to. |
| Description | The content of the description of the marker. |
| Recipe that added the search marker | The specific recipe that added the Search marker. |
Source files that errored on a recipe
org.openrewrite.table.SourcesFileErrorsThe details of all errors produced by a recipe run.
mod study . --last-recipe-run \
--data-table org.openrewrite.table.SourcesFileErrors
| Column | Description |
|---|---|
| Source path | The file that failed to parse. |
| Recipe that made changes | The specific recipe that made a change. |
| Stack trace | The stack trace of the failure. |
Recipe performance
org.openrewrite.table.RecipeRunStatsStatistics used in analyzing the performance of recipes.
mod study . --last-recipe-run \
--data-table org.openrewrite.table.RecipeRunStats
| Column | Description |
|---|---|
| The recipe | The recipe whose stats are being measured both individually and cumulatively. |
| Source file count | The number of source files the recipe ran over. |
| Source file changed count | The number of source files which were changed in the recipe run. Includes files created, deleted, and edited. |
| Cumulative scanning time (ns) | The total time spent across the scanning phase of this recipe. |
| Max scanning time (ns) | The max time scanning any one source file. |
| Cumulative edit time (ns) | The total time spent across the editing phase of this recipe. |
| Max edit time (ns) | The max time editing any one source file. |