Skip to main content
Moderne OnlyThis recipe is proprietary to Moderne and runs on the Moderne platform or CLI — it isn’t part of the open-source catalog. Available with a Moderne subscription.Contact Sales

Join each IMS transaction and job step to the segments behind it

Recipe IDio.moderne.mainframe.ims.AnalyzeImsChain
Artifactio.moderne.recipe:recipes-mainframe

Record what an IMS estate reaches, from whatever starts a program down to the segment: the transaction code or job step, the PSB, each of its PCBs, the database that PCB opens and the segments the program's calls name through it. A DL/I call names a position and never names a database, so the PSB is what closes it and which PSB a program runs under is written in a third file again. The DBDs and their segment hierarchies are reported alongside, with the field offsets a copybook reading a segment has to agree with, and so is what a field-sensitive PCB hands a program: where a PCB carries SENFLDs the I/O area is that field list and not the segment, so the copybook the program reads it with is a different length. FindImsChain answers the same questions and marks the calls and definitions in the source; this one produces the tables and changes nothing.

Single recipeOpenRewriteModerne Proprietary License
Try in PlatformTry this recipe in the Moderne platform. Not a user yet? You’ll get a no-setup demo environment, with nothing to install or configure.

Usage​

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.

shell
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.

mod config recipes jar install io.moderne.recipe:recipes-mainframe:RELEASE

Data tables​

IMS segment access
io.moderne.mainframe.analysis.table.ImsSegmentAccess

Every 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.

Export after a run
mod study . --last-recipe-run \
--data-table io.moderne.mainframe.analysis.table.ImsSegmentAccess
ColumnDescription
ProgramThe program making the call.
ParagraphThe paragraph or section the call is in.
InterfaceCBLTDLI, 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.
FunctionThe DL/I function, such as GU, GN, ISRT, REPL or DLET.
CRUDCREATE, READ, UPDATE, DELETE, CHECKPOINT or SYSTEM, from the function.
PSBThe 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.
PCBThe PCB as the PSB names it — its PCBNAME, else the PSB and the position, written CLMPSB02(3).
PCB positionThe 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.
MaskThe 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.
ReachesSEGMENT 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.
DatabaseThe 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 databaseThe 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.
SegmentsThe segments the call's search arguments name, space separated. A path call names several and reaches them all in the one call.
Source pathThe program's file.
LineThe one-based line the call is written on.
IMS chain
io.moderne.mainframe.analysis.table.ImsChain

One 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.

Export after a run
mod study . --last-recipe-run \
--data-table io.moderne.mainframe.analysis.table.ImsChain
ColumnDescription
Start kindTRANSACTION where a message schedules the PSB, JOB_STEP where a region step runs it.
StartThe transaction code, or the job.
StepThe job step, empty for a transaction.
ProgramThe 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 pathThe program's file, empty where it was not read here.
PSBThe PSB, which is what turns a PCB position into a database.
PSB pathThe PSB's file, empty where no gen source for it was read.
PCBThe PCB as the PSB names it — its PCBNAME, else the PSB and the position.
PCB positionThe PCB's one-based position among the PSB's PCB statements.
PCB typeDB 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 optionsThe PROCOPT the PCB opens the database with, which is what says whether the path is a read or a write.
DatabaseThe IMS database the PCB opens.
Database pathThe DBD's file, empty where no gen source for it was read.
Index databaseThe secondary index named on PROCSEQ, empty where the PCB has none.
Sensitive segmentsThe segments the PSB lets the program see through this PCB, space separated. GSAM has none.
SegmentsThe 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.ImsDatabases

One row per DBD: how it is organised, the DD names a job has to supply for it, and what it holds.

Export after a run
mod study . --last-recipe-run \
--data-table io.moderne.mainframe.analysis.table.ImsDatabases
ColumnDescription
DatabaseThe DBD name, which is what a PCB's DBDNAME and a stage 1 DATABASE macro name it by.
OrganizationHDAM, HIDAM, HISAM, INDEX, GSAM or LOGICAL — the first operand of ACCESS, which says how a segment is found.
Access methodThe operating system access method under it, VSAM or BSAM, from the second operand of ACCESS.
RandomizerThe RMNAME module an HDAM database hashes its root keys with, empty for every other organization.
DD namesThe 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 segmentThe segment with no parent, empty for GSAM, which has no segments at all.
SegmentsHow many segments the DBD defines.
FieldsHow many FIELD statements it defines across those segments.
Record lengthsThe RECORD lengths of a GSAM or HISAM data set group, space separated, empty where none is written.
ReferencesThe 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 pathThe gen source the DBD is written in.
LineThe one-based line of the DBD statement.
IMS segments
io.moderne.mainframe.analysis.table.ImsSegments

The 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.

Export after a run
mod study . --last-recipe-run \
--data-table io.moderne.mainframe.analysis.table.ImsSegments
ColumnDescription
DatabaseThe DBD the segment belongs to.
SegmentThe segment name, which is what a search argument's first eight bytes carry.
ParentThe physical parent, empty for the root.
LevelHow far down the hierarchy the segment sits, 1 for the root.
BytesThe 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 fieldThe field the segment is keyed on, empty where it has none.
Sequence startThe one-based byte the sequence field starts at, zero where there is none.
Sequence lengthHow many bytes the sequence field is, zero where there is none.
UniqueWhether the sequence field is unique, which is what decides whether two occurrences can share a key.
FieldsEvery FIELD of the segment, written CLMKEY 1(10) with a type where one is given, space separated and in source order.
Logical parentThe segment in another database this one is the logical child of, written CLMDBD02.POLROOT, empty where it is not one.
Logical childrenThe 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 indexesThe 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 pathThe gen source the segment is written in.
LineThe one-based line of the SEGM statement.
IMS field-sensitive I/O areas
io.moderne.mainframe.analysis.table.ImsFieldSensitiveAreas

What 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.

Export after a run
mod study . --last-recipe-run \
--data-table io.moderne.mainframe.analysis.table.ImsFieldSensitiveAreas
ColumnDescription
ProgramThe program making the call.
PSBThe PSB the program runs under.
PCBThe PCB as the PSB names it — its PCBNAME, else the PSB and the position, written CLMPSB02(2).
SegmentThe segment the SENSEG names, which is the one the call asks for.
Sensitive fieldsThe 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 bytesHow 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 areaThe data item the call moves the segment into.
CopybookThe copybook that declares the I/O area, empty where the program declares it itself.
Copybook bytesHow many bytes that declaration describes, zero where it cannot be laid out.
VerdictMATCH 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 pathThe program's file.
LineThe one-based line the call is written on.
Findings
io.moderne.mainframe.analysis.table.Findings

Everything the mainframe analyses found wrong, ranked, with the evidence for each and the line it is on. Sort on priority.

Export after a run
mod study . --last-recipe-run \
--data-table io.moderne.mainframe.analysis.table.Findings
ColumnDescription
Priority1 for CRITICAL down to 4 for LOW, so the table sorts.
SeverityCRITICAL 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.
CategoryWhat 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.
ProgramThe COBOL program, or the copybook where the finding is about one.
SummaryThe finding in one sentence, written to be read on its own.
EvidenceWhy 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.
WhereThe paragraph, section or data item the finding is in.
Source pathThe file, so the finding can be opened.
COBOL relationships
org.openrewrite.mainframe.cobol.table.CobolRelationships

Relationships between different COBOL resources.

Export after a run
mod study . --last-recipe-run \
--data-table org.openrewrite.mainframe.cobol.table.CobolRelationships
ColumnDescription
DependentThe resource that defines the relationship.
Dependent typeThe resource type of the resource that defines the relationship.
ActionThe action that links the dependent and dependency.
DependencyThe resource that is exercised or linked to.
Dependency typeThe resource type of the resource that is exercised or linked to.
Dependency missingIndicates whether the dependency is a known resource.
Action metadataAdditional data about the action.
Dependent pathThe source file the dependent's statement was written in, or null when the dependent is a name that has no source here.
Dependent lineThe one-based line the dependent's statement was written on, or null when it has no source here.
Dependency pathThe 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 lineThe 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.SourcesFileResults

Source files that were modified by the recipe run.

Export after a run
mod study . --last-recipe-run \
--data-table org.openrewrite.table.SourcesFileResults
ColumnDescription
Source path before the runThe source path of the file before the run. null when a source file was created during the run.
Source path after the runA 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 changesIn 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 changesThe specific recipe that made a change.
Estimated time savingAn estimated effort that a developer to fix manually instead of using this recipe, in unit of seconds.
CycleThe recipe cycle in which the change was made.
Source files that had search results
org.openrewrite.table.SearchResults

Search results that were found during the recipe run.

Export after a run
mod study . --last-recipe-run \
--data-table org.openrewrite.table.SearchResults
ColumnDescription
Source path of search result before the runThe source path of the file with the search result markers present.
Source path of search result after run the runA recipe may modify the source path. This is the path after the run. null when a source file was deleted during the run.
ResultThe trimmed printed tree of the LST element that the marker is attached to.
DescriptionThe content of the description of the marker.
Recipe that added the search markerThe specific recipe that added the Search marker.
Source files that errored on a recipe
org.openrewrite.table.SourcesFileErrors

The details of all errors produced by a recipe run.

Export after a run
mod study . --last-recipe-run \
--data-table org.openrewrite.table.SourcesFileErrors
ColumnDescription
Source pathThe file that failed to parse.
Recipe that made changesThe specific recipe that made a change.
Stack traceThe stack trace of the failure.
Recipe performance
org.openrewrite.table.RecipeRunStats

Statistics used in analyzing the performance of recipes.

Export after a run
mod study . --last-recipe-run \
--data-table org.openrewrite.table.RecipeRunStats
ColumnDescription
The recipeThe recipe whose stats are being measured both individually and cumulatively.
Source file countThe number of source files the recipe ran over.
Source file changed countThe 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.