Before relational databases existed, before SQL was invented, before DB2 processed its first query, there was IMS. IBM's Information Management System debuted in 1966 as the database system for the Apollo space program, tracking the millions of...
In This Chapter
- Introduction: The Original Enterprise Database
- 26.1 The Hierarchical Data Model
- 26.2 The DL/I Call Interface (CBLTDLI)
- 26.3 PCBs and PSBs: The Program's View of the Database
- 26.4 Segment Search Arguments (SSAs)
- 26.5 Database Retrieval Calls: GU, GN, GNP, GHU, GHN, GHNP
- 26.6 Database Update Calls: ISRT, REPL, DLET
- 26.7 Status Code Handling
- 26.8 Complete Example: Reading an IMS Database
- 26.9 Complete Example: Updating an IMS Database
- 26.10 IMS Transaction Manager (IMS TM/DC)
- 26.11 MPP vs. BMP Regions
- 26.12 Checkpoint and Restart
- 26.13 JCL for IMS Batch Programs
- 26.14 Hierarchical Database Navigation Patterns
- 26.15 IMS-COBOL Integration Patterns
- 26.16 Hands-On Practice with IBM Z Xplore
- 26.17 IMS in Modern Architectures
- What You Have Learned
Chapter 26: IMS Database and Transaction Management
IBM Enterprise COBOL
Introduction: The Original Enterprise Database
Before relational databases existed, before SQL was invented, before DB2 processed its first query, there was IMS. IBM's Information Management System debuted in 1966 as the database system for the Apollo space program, tracking the millions of parts needed to build the Saturn V rocket. Each rocket contained roughly 3.5 million parts, organized in a natural hierarchy: rocket to stage, stage to assembly, assembly to subassembly, subassembly to component. A hierarchical database was the natural fit.
That same hierarchical model proved equally natural for business data. A bank has customers. Each customer has accounts. Each account has transactions. A hospital has patients. Each patient has visits. Each visit has diagnoses and procedures. An insurance company has policies. Each policy has claims. Each claim has payments. These are parent-child relationships -- trees -- and IMS stores them exactly that way.
Nearly sixty years later, IMS remains in production at the world's largest financial institutions. An estimated 95% of Fortune 1000 companies have IMS databases in their enterprise stack. IMS processes over 50 billion transactions per day globally. Major banks run their core deposit and loan systems on IMS. Airlines manage reservations through IMS. Government agencies store citizen records in IMS hierarchies that were designed decades ago and continue to function with extraordinary reliability.
IMS is really two subsystems in one. IMS DB (Database Manager) is the hierarchical database engine that stores and retrieves data through the DL/I (Data Language/I) call interface. IMS TM (Transaction Manager), also known as IMS DC (Data Communications), is the online transaction processing system that manages terminals, queues messages, and dispatches application programs -- much like CICS does for its environment. A COBOL program running under IMS uses DL/I calls both to access the database and to communicate with terminals.
This chapter teaches you to write COBOL programs that interact with IMS databases and process IMS transactions. You will learn the hierarchical data model, the DL/I call interface, Program Communication Blocks (PCBs) and Program Specification Blocks (PSBs), Segment Search Arguments (SSAs), all major database calls, the IMS Transaction Manager message processing model, checkpoint/restart for batch recovery, and the JCL required to execute IMS batch programs. Every concept is illustrated with complete COBOL code using a banking customer-account-transaction hierarchy.
[IBM Enterprise COBOL] IMS is an IBM mainframe product that runs exclusively on z/OS. It cannot be installed on Linux, Windows, or macOS, and there is no GnuCOBOL equivalent. If you want hands-on practice, IBM Z Xplore (formerly IBM Z Open Education) provides free access to a real z/OS system with IMS capabilities. Instructions for accessing Z Xplore appear at the end of this chapter.
26.1 The Hierarchical Data Model
Trees, Not Tables
Relational databases store data in two-dimensional tables (rows and columns) connected by foreign keys. IMS stores data in tree structures -- hierarchies -- where each record (called a segment) has at most one parent and can have multiple children. The root segment sits at the top with no parent. Every other segment hangs below its parent in a strictly defined tree.
Consider a banking database. The natural hierarchy looks like this:
CUSTOMER (root segment)
|
+-- ACCOUNT (child of CUSTOMER)
| |
| +-- TRANSACTION (child of ACCOUNT)
|
+-- ADDRESS (child of CUSTOMER)
|
+-- CONTACT (child of CUSTOMER)
Customer CUST000100 might have three accounts (checking, savings, loan). The checking account might have fifty transactions. The customer also has a mailing address and a billing address, plus phone and email contacts. All of this hangs under the single CUSTOMER root in a tree.
Key Terminology
| Term | Definition |
|---|---|
| Segment | The basic unit of data in IMS, equivalent to a record or row. Each segment has a defined layout of fields. |
| Segment Type | The template definition for a class of segments (e.g., CUSTOMER, ACCOUNT). Defined in the DBD. |
| Root Segment | The topmost segment in a hierarchy. Every hierarchy has exactly one root segment type. |
| Parent Segment | A segment that has one or more child segment types defined beneath it. |
| Child Segment | A segment that exists under a parent. A child cannot exist without its parent. |
| Twin Segments | Multiple occurrences of the same segment type under the same parent. Customer CUST000100 might have three ACCOUNT twins. |
| Hierarchical Path | The chain of segments from the root down to a specific segment. |
| Sequence Field | The key field within a segment type, used for ordering and direct access. |
| Database Record | One complete root segment together with all its dependent (child) segments at all levels. |
| DBD | Database Description -- a control block that defines the physical structure of the database (segment types, fields, hierarchical relationships, access methods). |
| PSB | Program Specification Block -- a control block that defines a program's view of one or more databases (which segments are visible, what operations are allowed). |
| PCB | Program Communication Block -- one component of a PSB, representing a single database view. A PSB can contain multiple PCBs. |
Hierarchical Sequence
IMS traverses a database in hierarchical sequence -- a depth-first, left-to-right traversal of the tree. For the banking hierarchy above, the hierarchical sequence visits:
- CUSTOMER (root)
- First ACCOUNT under this customer
- First TRANSACTION under that account
- Second TRANSACTION under that account
- (all remaining TRANSACTIONs)
- Second ACCOUNT under this customer
- First TRANSACTION under the second account
- (and so on through all accounts and transactions)
- First ADDRESS under this customer
- Second ADDRESS
- First CONTACT
- (and so on)
- Next CUSTOMER root (next database record)
This traversal order matters because the Get Next (GN) call returns segments in exactly this sequence.
Physical Database Organizations
[IBM Enterprise COBOL] IMS supports several physical storage organizations for databases:
| Organization | Abbreviation | Description |
|---|---|---|
| Hierarchical Sequential Access Method | HSAM | Sequential, read-only access. Used for archival data. |
| Hierarchical Indexed Sequential | HISAM | Indexed sequential access using VSAM KSDS. Good for moderate-size databases with key access. |
| Hierarchical Direct Access Method | HDAM | Direct (hashed) access to root segments. Fastest for random access by key. |
| Hierarchical Indexed Direct | HIDAM | Indexed access to root segments with direct access to dependents. Best for both random and sequential access. |
| Fast Path DEDB | DEDB | Data Entry Database. High-performance option for very high-volume online transaction processing. |
The database organization is transparent to the COBOL application programmer. Your DL/I calls work the same way regardless of whether the database is HDAM or HIDAM. The choice of organization is made by the database administrator when creating the DBD, based on access patterns and performance requirements.
26.2 The DL/I Call Interface (CBLTDLI)
How COBOL Talks to IMS
Every interaction between a COBOL program and IMS goes through DL/I (Data Language/I), IMS's call-level interface. In COBOL, you invoke DL/I using the CALL 'CBLTDLI' statement. CBLTDLI is the COBOL-specific entry point to the DL/I interface (the "CBL" prefix stands for COBOL; assembler programs use ASMTDLI, PL/I programs use PLITDLI).
The general format of every DL/I call from COBOL is:
CALL 'CBLTDLI' USING function-code
pcb-mask
io-area
ssa-1
ssa-2
...
The parameters are:
- Function code: A 4-byte field specifying the operation (GU, GN, GNP, GHU, GHN, GHNP, ISRT, REPL, DLET, CHKP, XRST, and others).
- PCB mask: The Program Communication Block address, defined in the LINKAGE SECTION and received through the PROCEDURE DIVISION USING clause.
- I/O area: A WORKING-STORAGE area where segment data is placed (on retrieval) or taken from (on insert/replace).
- SSAs (optional): Zero or more Segment Search Arguments that qualify the call -- specifying which segment to access and how to reach it.
Defining Function Codes
Function codes are simple 4-byte alphanumeric values. Define them in WORKING-STORAGE:
WORKING-STORAGE SECTION.
*
* DL/I function codes
01 DLI-GU PIC X(4) VALUE 'GU '.
01 DLI-GN PIC X(4) VALUE 'GN '.
01 DLI-GNP PIC X(4) VALUE 'GNP '.
01 DLI-GHU PIC X(4) VALUE 'GHU '.
01 DLI-GHN PIC X(4) VALUE 'GHN '.
01 DLI-GHNP PIC X(4) VALUE 'GHNP'.
01 DLI-ISRT PIC X(4) VALUE 'ISRT'.
01 DLI-REPL PIC X(4) VALUE 'REPL'.
01 DLI-DLET PIC X(4) VALUE 'DLET'.
01 DLI-CHKP PIC X(4) VALUE 'CHKP'.
01 DLI-XRST PIC X(4) VALUE 'XRST'.
Note that each value is exactly 4 bytes, padded with spaces. IMS is strict about this format.
Defining I/O Areas
The I/O area is where IMS places segment data on a retrieval call, and where your program places data before an insert or replace. Define one I/O area for each segment type you work with:
* I/O area for CUSTOMER segment
01 CUSTOMER-SEGMENT.
05 CUST-ID PIC X(10).
05 CUST-NAME PIC X(30).
05 CUST-ADDRESS PIC X(50).
05 CUST-CITY PIC X(20).
05 CUST-STATE PIC X(2).
05 CUST-ZIP PIC X(10).
05 CUST-PHONE PIC X(15).
05 CUST-TYPE PIC X(1).
88 CUST-INDIVIDUAL VALUE 'I'.
88 CUST-COMMERCIAL VALUE 'C'.
05 CUST-OPEN-DATE PIC X(10).
05 CUST-STATUS PIC X(1).
88 CUST-ACTIVE VALUE 'A'.
88 CUST-INACTIVE VALUE 'I'.
88 CUST-CLOSED VALUE 'C'.
* I/O area for ACCOUNT segment
01 ACCOUNT-SEGMENT.
05 ACCT-NUMBER PIC X(12).
05 ACCT-TYPE PIC X(2).
88 ACCT-CHECKING VALUE 'CK'.
88 ACCT-SAVINGS VALUE 'SV'.
88 ACCT-LOAN VALUE 'LN'.
05 ACCT-BALANCE PIC S9(11)V99 COMP-3.
05 ACCT-OPEN-DATE PIC X(10).
05 ACCT-STATUS PIC X(1).
05 ACCT-INTEREST-RATE PIC S9(3)V9(4) COMP-3.
* I/O area for TRANSACTION segment
01 TRANSACTION-SEGMENT.
05 TRAN-ID PIC X(15).
05 TRAN-DATE PIC X(10).
05 TRAN-TIME PIC X(8).
05 TRAN-TYPE PIC X(2).
88 TRAN-DEPOSIT VALUE 'DP'.
88 TRAN-WITHDRAWAL VALUE 'WD'.
88 TRAN-TRANSFER VALUE 'XF'.
05 TRAN-AMOUNT PIC S9(11)V99 COMP-3.
05 TRAN-DESC PIC X(30).
The layout of each I/O area must match the segment definition in the DBD exactly -- same field order, same lengths, same data types. If they do not match, your program will read garbage or corrupt the database.
26.3 PCBs and PSBs: The Program's View of the Database
What Is a PSB?
A Program Specification Block (PSB) defines a COBOL program's authorized view of IMS databases. It specifies which databases the program can access, which segments within each database are visible (this is called segment sensitivity), and what operations are permitted (read, insert, replace, delete). The PSB is created by the DBA using IMS utility statements and stored in the IMS PSBLIB.
A PSB contains one or more Program Communication Blocks (PCBs). Each PCB represents either a database view or the I/O PCB for terminal/message processing.
The IO PCB
Every IMS program receives an IO PCB as its first PCB. The IO PCB provides status information for system-level calls (checkpoint, restart) and, in online programs, handles message I/O with terminals. Even batch programs that never communicate with a terminal receive the IO PCB.
Define the IO PCB mask in the LINKAGE SECTION:
LINKAGE SECTION.
*
* IO PCB Mask (always the first PCB in the PSB)
01 IO-PCB-MASK.
05 IO-LTERM-NAME PIC X(8).
05 FILLER PIC X(2).
05 IO-STATUS-CODE PIC X(2).
05 IO-DATE PIC S9(7) COMP-3.
05 IO-TIME PIC S9(7) COMP-3.
05 IO-MSG-SEQ-NUM PIC S9(7) COMP-3.
05 IO-MOD-NAME PIC X(8).
The IO-STATUS-CODE field tells you the result of system calls. For message processing, a status code of QC means no more messages are available.
DB PCB Masks
Each database the program accesses has its own DB PCB. The DB PCB mask tells you, after every DL/I call, what happened:
* DB PCB Mask for CUSTOMER database
01 CUST-DB-PCB-MASK.
05 CUST-DBD-NAME PIC X(8).
05 CUST-SEG-LEVEL PIC X(2).
05 CUST-STATUS-CODE PIC X(2).
05 CUST-PROC-OPTIONS PIC X(4).
05 FILLER PIC S9(5) COMP.
05 CUST-SEG-NAME PIC X(8).
05 CUST-KEY-LENGTH PIC S9(5) COMP.
05 CUST-NUM-SENS-SEGS PIC S9(5) COMP.
05 CUST-KEY-FEEDBACK PIC X(30).
The key fields in the DB PCB mask are:
| Field | Description |
|---|---|
| DBD-NAME | The name of the Database Description. Matches the DBD in the IMS catalog. |
| SEG-LEVEL | The hierarchical level number of the last segment accessed (01 = root, 02 = first child level, etc.). |
| STATUS-CODE | The result of the last DL/I call. Spaces means success. Non-blank codes indicate conditions or errors. |
| PROC-OPTIONS | The processing options allowed for this PCB (G=Get, I=Insert, R=Replace, D=Delete). |
| SEG-NAME | The name of the last segment type accessed. |
| KEY-LENGTH | The length of the concatenated key. |
| NUM-SENS-SEGS | The number of segment types this PCB is sensitive to. |
| KEY-FEEDBACK | The concatenated key of the current position in the database. Contains keys from the root down to the current segment. |
Receiving PCBs in the PROCEDURE DIVISION
IMS passes PCB addresses to your program through the PROCEDURE DIVISION USING clause. The PCBs must appear in the same order they are defined in the PSB:
PROCEDURE DIVISION USING IO-PCB-MASK
CUST-DB-PCB-MASK.
For programs that access multiple databases:
PROCEDURE DIVISION USING IO-PCB-MASK
CUST-DB-PCB
PROD-DB-PCB.
The order is critical. The first parameter is always the IO PCB. Subsequent parameters are DB PCBs in the order they appear in the PSB definition. If you get the order wrong, your program will use the wrong PCB for calls and produce unpredictable results.
Multiple PCBs in Practice
A program that needs to access both a CUSTOMER database (for reading and updating) and a PRODUCT database (for read-only reference lookups) would have a PSB with three PCBs:
- IO PCB (always first)
- CUSTOMER DB PCB (processing options: GIRD -- Get, Insert, Replace, Delete)
- PRODUCT DB PCB (processing options: G -- Get only)
Each DL/I call specifies which PCB to use, directing the call to the correct database:
* Access the CUSTOMER database
CALL 'CBLTDLI' USING DLI-GU
CUST-DB-PCB
CUSTOMER-IO-AREA
CUST-QUAL-SSA
* Access the PRODUCT database
CALL 'CBLTDLI' USING DLI-GU
PROD-DB-PCB
PRODUCT-IO-AREA
PROD-QUAL-SSA
Each PCB maintains its own independent position within its database. Calls against the CUSTOMER PCB do not affect the position in the PRODUCT database, and vice versa.
26.4 Segment Search Arguments (SSAs)
Directing the DL/I Call
Segment Search Arguments tell IMS which segment to access. Without SSAs, DL/I calls operate on whatever the next segment happens to be in hierarchical sequence. With SSAs, you can specify exactly which segment type, which key value, and which path through the hierarchy you want.
Unqualified SSAs
An unqualified SSA specifies only the segment type name. It is exactly 9 bytes: 8 bytes for the segment name (padded with spaces) plus 1 trailing space:
* Unqualified SSAs - segment name only (9 bytes)
01 CUST-UNQUAL-SSA PIC X(9) VALUE 'CUSTOMER '.
01 ACCT-UNQUAL-SSA PIC X(9) VALUE 'ACCOUNT '.
01 TRAN-UNQUAL-SSA PIC X(9) VALUE 'TRANSACT '.
An unqualified SSA on a GN call says "give me the next segment of this type" without specifying which one. An unqualified SSA on a GNP call says "give me the next child of this type under the current parent."
Qualified SSAs
A qualified SSA adds a search condition -- a field name, a comparison operator, and a value. The format is:
segment-name(field-name OP value)
Where OP is one of: =, >=, <=, >, <, != (not equal).
In COBOL, define qualified SSAs as group items so you can set the key value dynamically:
* Qualified SSA for CUSTOMER by key
01 CUST-QUAL-SSA.
05 FILLER PIC X(9) VALUE 'CUSTOMER('.
05 FILLER PIC X(10) VALUE 'CUSTID ='.
05 CUST-SSA-KEY PIC X(10) VALUE SPACES.
05 FILLER PIC X(1) VALUE ')'.
* Qualified SSA for ACCOUNT by key
01 ACCT-QUAL-SSA.
05 FILLER PIC X(9) VALUE 'ACCOUNT ('.
05 FILLER PIC X(10) VALUE 'ACCTNO ='.
05 ACCT-SSA-KEY PIC X(12) VALUE SPACES.
05 FILLER PIC X(1) VALUE ')'.
Before issuing the DL/I call, move the desired key value into the SSA:
MOVE 'CUST000100' TO CUST-SSA-KEY
CALL 'CBLTDLI' USING DLI-GU
CUST-DB-PCB-MASK
CUSTOMER-SEGMENT
CUST-QUAL-SSA
This GU call says: "Go directly to the CUSTOMER segment whose CUSTID field equals CUST000100."
Boolean SSAs (Multiple Qualifications)
You can combine multiple conditions in a single SSA using * (AND) or + (OR) between qualifications:
* Boolean SSA: Active AND Individual customers
01 CUST-BOOLEAN-SSA.
05 FILLER PIC X(9) VALUE 'CUSTOMER('.
05 FILLER PIC X(10) VALUE 'CUSTSTAT ='.
05 BOOL-STATUS PIC X(1) VALUE 'A'.
05 FILLER PIC X(1) VALUE '*'.
05 FILLER PIC X(10) VALUE 'CUSTTYPE ='.
05 BOOL-TYPE PIC X(1) VALUE 'I'.
05 FILLER PIC X(1) VALUE ')'.
The * between the two qualifications acts as a logical AND. A GN call with this SSA returns only customer segments that are both active (status = 'A') and individual (type = 'I').
SSA Command Codes
Command codes modify how DL/I processes a call. They are placed in position 9 of the SSA, preceded by an asterisk:
segment-name*C(qualification)
Where C is the command code letter.
| Code | Name | Description |
|---|---|---|
| D | Path | Retrieves the segment along the path (used with path calls to return multiple segments). |
| F | First | Go to the first occurrence of this segment type under the parent. |
| L | Last | Go to the last occurrence of this segment type under the parent. |
| N | No position change | Do not update current position at this level. |
| P | Set parentage | Establish parentage at this level so subsequent GNP calls return children of this segment. |
| U | Maintain position | Maintain current position at this level after the call. |
Example: SSA with the F (First) command code to get the first account:
* SSA with F (first) command code
01 ACCT-FIRST-SSA.
05 FILLER PIC X(9) VALUE 'ACCOUNT *'.
05 FILLER PIC X(1) VALUE 'F'.
Example: SSA with the D (path) command code:
* SSA with D (path) command code
01 CUST-PATH-SSA.
05 FILLER PIC X(9) VALUE 'CUSTOMER*'.
05 FILLER PIC X(1) VALUE 'D'.
05 FILLER PIC X(1) VALUE '('.
05 FILLER PIC X(10) VALUE 'CUSTID ='.
05 CUST-PATH-KEY PIC X(10) VALUE SPACES.
05 FILLER PIC X(1) VALUE ')'.
The D command code in a path call tells IMS to retrieve the customer segment along with a lower-level segment in a single call, making the navigation more efficient.
Path SSAs: Multi-Level Qualification
You can provide SSAs for multiple levels of the hierarchy to navigate a complete path in a single call:
* Navigate CUSTOMER -> ACCOUNT -> TRANSACTION in one call
MOVE 'CUST000100' TO CUST-SSA-KEY
MOVE '999000000001' TO ACCT-SSA-KEY
CALL 'CBLTDLI' USING DLI-GU
CUST-DB-PCB-MASK
TRANSACTION-SEGMENT
CUST-QUAL-SSA
ACCT-QUAL-SSA
TRAN-UNQUAL-SSA
This single GU call navigates three levels deep: position to customer CUST000100, then to account 999000000001 under that customer, then to the first transaction under that account. The TRANSACTION-SEGMENT I/O area receives the transaction data.
26.5 Database Retrieval Calls: GU, GN, GNP, GHU, GHN, GHNP
IMS provides six retrieval calls, organized into two categories: standard retrieval and hold retrieval.
GU -- Get Unique (Direct Access)
GU navigates directly to a specific segment based on qualified SSAs. It repositions the database regardless of where you were before. Think of GU as a "random access" call -- it goes straight to the target.
* Get Unique: Direct access to customer CUST000100
MOVE 'CUST000100' TO CUST-SSA-KEY
CALL 'CBLTDLI' USING DLI-GU
CUST-DB-PCB-MASK
CUSTOMER-SEGMENT
CUST-QUAL-SSA
EVALUATE CUST-STATUS-CODE
WHEN SPACES
DISPLAY 'Customer found: ' CUST-NAME
WHEN 'GE'
DISPLAY 'Customer not found'
WHEN OTHER
DISPLAY 'DL/I error: ' CUST-STATUS-CODE
PERFORM 9999-DLI-ERROR
END-EVALUATE
Status code spaces means the segment was found and placed in the I/O area. Status code GE means no segment matched the SSA criteria.
GN -- Get Next (Sequential Access)
GN retrieves the next segment in hierarchical sequence. It moves forward from the current position. Use GN with an unqualified SSA to read all segments of a particular type sequentially:
* Get Next: Read all customers sequentially
MOVE 0 TO WS-CUSTOMER-COUNT
SET NOT-END-OF-DATABASE TO TRUE
PERFORM UNTIL END-OF-DATABASE
CALL 'CBLTDLI' USING DLI-GN
CUST-DB-PCB-MASK
CUSTOMER-SEGMENT
CUST-UNQUAL-SSA
EVALUATE CUST-STATUS-CODE
WHEN SPACES
ADD 1 TO WS-CUSTOMER-COUNT
DISPLAY 'Customer: ' CUST-ID
' - ' CUST-NAME
WHEN 'GB'
SET END-OF-DATABASE TO TRUE
WHEN 'GE'
SET END-OF-DATABASE TO TRUE
WHEN OTHER
DISPLAY 'GN error: ' CUST-STATUS-CODE
PERFORM 9999-DLI-ERROR
END-EVALUATE
END-PERFORM
Status code GB means the end of the database has been reached. Status code GE means no more segments of the requested type were found.
GNP -- Get Next within Parent
GNP retrieves the next segment within the scope of the currently established parent. It only returns child segments under the current parent -- it never crosses a parent boundary.
The pattern is: first use GU to position to a parent, then use GNP in a loop to read all children:
* Position to the parent customer
MOVE 'CUST000100' TO CUST-SSA-KEY
CALL 'CBLTDLI' USING DLI-GU
CUST-DB-PCB-MASK
CUSTOMER-SEGMENT
CUST-QUAL-SSA
* Then read all ACCOUNT children using GNP
PERFORM UNTIL END-OF-DATABASE
CALL 'CBLTDLI' USING DLI-GNP
CUST-DB-PCB-MASK
ACCOUNT-SEGMENT
ACCT-UNQUAL-SSA
EVALUATE CUST-STATUS-CODE
WHEN SPACES
ADD 1 TO WS-ACCOUNT-COUNT
ADD ACCT-BALANCE TO WS-TOTAL-BALANCE
MOVE ACCT-BALANCE TO WS-DISPLAY-BALANCE
DISPLAY ' Account: ' ACCT-NUMBER
' Type: ' ACCT-TYPE
' Balance: ' WS-DISPLAY-BALANCE
WHEN 'GE'
SET END-OF-DATABASE TO TRUE
WHEN 'GP'
SET END-OF-DATABASE TO TRUE
WHEN OTHER
DISPLAY 'GNP error: ' CUST-STATUS-CODE
PERFORM 9999-DLI-ERROR
END-EVALUATE
END-PERFORM
The GE status from GNP means there are no more segments of the requested type under the parent. The GP status (rare) indicates a parentage problem.
GHU, GHN, GHNP -- Hold Variants
The "hold" variants (GHU, GHN, GHNP) work identically to their non-hold counterparts except that they place a hold on the retrieved segment. The hold is required before you can issue a REPL (Replace) or DLET (Delete) call. This is IMS's way of ensuring that you do not update or delete a segment you have not actually retrieved.
* Get Hold Unique: Retrieve with hold for update
MOVE 'CUST000100' TO CUST-SSA-KEY
CALL 'CBLTDLI' USING DLI-GHU
CUST-DB-PCB-MASK
CUSTOMER-SEGMENT
CUST-QUAL-SSA
IF CUST-STATUS-CODE = SPACES
DISPLAY 'Customer retrieved with hold: '
CUST-NAME
DISPLAY '(Segment can now be updated or deleted)'
END-IF
The hold is released after a REPL call, a DLET call, or any subsequent non-hold Get call. If you issue another GU (without H), the hold from the previous GHU is released.
26.6 Database Update Calls: ISRT, REPL, DLET
ISRT -- Insert
ISRT adds a new segment to the database. For a root segment, provide an unqualified SSA. For a child segment, provide qualified SSAs for the parent path plus an unqualified SSA for the segment being inserted.
Inserting a root segment:
* Build the new customer segment
INITIALIZE CUSTOMER-SEGMENT
MOVE 'CUST000999' TO CUST-ID
MOVE 'JOHNSON, ROBERT A' TO CUST-NAME
MOVE '1234 OAK AVENUE' TO CUST-ADDRESS
MOVE 'CHICAGO' TO CUST-CITY
MOVE 'IL' TO CUST-STATE
MOVE '60601' TO CUST-ZIP
MOVE '312-555-0199' TO CUST-PHONE
MOVE 'I' TO CUST-TYPE
MOVE WS-FORMATTED-DATE TO CUST-OPEN-DATE
MOVE 'A' TO CUST-STATUS
* Insert the root segment
CALL 'CBLTDLI' USING DLI-ISRT
CUST-DB-PCB-MASK
CUSTOMER-SEGMENT
CUST-UNQUAL-SSA
EVALUATE CUST-STATUS-CODE
WHEN SPACES
DISPLAY 'Customer inserted: ' CUST-ID
WHEN 'II'
DISPLAY 'Duplicate key: ' CUST-ID
WHEN OTHER
DISPLAY 'ISRT error: ' CUST-STATUS-CODE
END-EVALUATE
Status code II means a segment with the same key already exists.
Inserting a child segment under a parent:
* Set the parent's key in the qualified SSA
MOVE 'CUST000999' TO CUST-SSA-KEY
* Build the new account segment
INITIALIZE ACCOUNT-SEGMENT
MOVE '999000000001' TO ACCT-NUMBER
MOVE 'CK' TO ACCT-TYPE
MOVE 1500.00 TO ACCT-BALANCE
MOVE WS-FORMATTED-DATE TO ACCT-OPEN-DATE
MOVE 'A' TO ACCT-STATUS
MOVE 0.0025 TO ACCT-INTEREST-RATE
* Insert account under the parent customer
CALL 'CBLTDLI' USING DLI-ISRT
CUST-DB-PCB-MASK
ACCOUNT-SEGMENT
CUST-QUAL-SSA
ACCT-UNQUAL-SSA
The CUST-QUAL-SSA identifies the parent customer. The ACCT-UNQUAL-SSA identifies the segment type being inserted. IMS locates the parent first, then inserts the child in key sequence under it.
Inserting a grandchild segment (three levels deep):
* Set SSA keys for the full path
MOVE 'CUST000999' TO CUST-SSA-KEY
MOVE '999000000001' TO ACCT-SSA-KEY
* Insert transaction under customer/account path
CALL 'CBLTDLI' USING DLI-ISRT
CUST-DB-PCB-MASK
TRANSACTION-SEGMENT
CUST-QUAL-SSA
ACCT-QUAL-SSA
TRAN-UNQUAL-SSA
REPL -- Replace (Update)
REPL updates a segment that was previously retrieved with a hold call (GHU, GHN, or GHNP). You modify the I/O area fields (except the key field) and then issue REPL:
* Step 1: Retrieve the segment with hold
MOVE 'CUST000999' TO CUST-SSA-KEY
CALL 'CBLTDLI' USING DLI-GHU
CUST-DB-PCB-MASK
CUSTOMER-SEGMENT
CUST-QUAL-SSA
IF CUST-STATUS-CODE NOT = SPACES
DISPLAY 'GHU failed: ' CUST-STATUS-CODE
GO TO 5000-EXIT
END-IF
* Step 2: Modify non-key fields ONLY
* WARNING: Never change the key field (CUST-ID)!
MOVE '5678 MAPLE BOULEVARD' TO CUST-ADDRESS
MOVE 'EVANSTON' TO CUST-CITY
MOVE '60201' TO CUST-ZIP
* Step 3: Issue REPL -- no SSA needed
CALL 'CBLTDLI' USING DLI-REPL
CUST-DB-PCB-MASK
CUSTOMER-SEGMENT
EVALUATE CUST-STATUS-CODE
WHEN SPACES
DISPLAY 'Customer updated successfully'
WHEN 'DJ'
DISPLAY 'Error: no prior hold call'
WHEN 'DA'
DISPLAY 'Error: key field was changed'
WHEN OTHER
DISPLAY 'REPL error: ' CUST-STATUS-CODE
END-EVALUATE
Critical rules for REPL:
- You must issue a hold call (GHU, GHN, GHNP) before REPL.
- You must not change the key field of the segment.
- REPL does not use SSAs -- it updates the segment that was held.
- Status code DJ means you did not issue a prior hold call.
- Status code DA means you modified the key field.
DLET -- Delete
DLET removes a segment and all its dependent children. Like REPL, it requires a prior hold call:
* Retrieve and hold the segment to delete
CALL 'CBLTDLI' USING DLI-GHU
CUST-DB-PCB-MASK
CUSTOMER-SEGMENT
CUST-QUAL-SSA
IF CUST-STATUS-CODE = SPACES
* Delete the segment (and all its children!)
CALL 'CBLTDLI' USING DLI-DLET
CUST-DB-PCB-MASK
CUSTOMER-SEGMENT
IF CUST-STATUS-CODE = SPACES
DISPLAY 'Segment deleted'
END-IF
END-IF
Important: Deleting a parent segment deletes all its children and grandchildren. If you DLET a CUSTOMER segment, all ACCOUNT, TRANSACTION, ADDRESS, and CONTACT segments under it are also deleted. This is called a cascade delete and it is automatic.
26.7 Status Code Handling
After every DL/I call, check the status code in the PCB mask. The status code is the single most important field for program logic. Here is a comprehensive reference:
Common Status Codes
| Code | Meaning | Typical Action |
|---|---|---|
(spaces) |
Successful call | Continue processing |
GE |
Segment not found | Handle not-found condition |
GB |
End of database reached | Stop sequential processing |
GK |
Segment type changed (GN returned a different type) | Check segment name in PCB |
GP |
Parentage changed (GNP went outside parent scope) | Stop child processing |
II |
Duplicate key on insert | Handle duplicate |
DA |
Key field changed before REPL | Programming error -- fix code |
DJ |
No prior hold call for REPL/DLET | Programming error -- fix code |
AI |
Program not authorized for database | PSB configuration error |
AK |
Invalid SSA for PCB sensitivity | SSA references segment not in PCB |
QC |
No more messages (IO PCB, online) | End message processing loop |
A Robust Error Handler
9999-DLI-ERROR.
DISPLAY '*** CRITICAL DL/I ERROR ***'
DISPLAY 'Status code : ' CUST-STATUS-CODE
DISPLAY 'Segment name: ' CUST-SEG-NAME
DISPLAY 'DBD name : ' CUST-DBD-NAME
DISPLAY 'Segment lvl : ' CUST-SEG-LEVEL
GOBACK.
For production programs, you should log the error to a file, issue an abend with a meaningful code, or (in online programs) send an error message to the terminal and continue processing the next message.
26.8 Complete Example: Reading an IMS Database
The following program demonstrates all the major read operations against the banking hierarchy. It performs a GU (direct access), a GN loop (sequential scan), a GNP loop (children within a parent), and a GHU (hold for potential update). This corresponds to example-01-ims-db-read.cob in the code examples.
*================================================================*
* IMS DB READ OPERATIONS - COMPLETE EXAMPLE *
* Demonstrates: GU, GN, GNP, GHU calls *
* Database: CUSTOMER -> ACCOUNT -> TRANSACTION *
* [IBM Enterprise COBOL] - IMS DL/I interface *
*================================================================*
IDENTIFICATION DIVISION.
PROGRAM-ID. IMSREAD1.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SOURCE-COMPUTER. IBM-ZOS.
OBJECT-COMPUTER. IBM-ZOS.
DATA DIVISION.
WORKING-STORAGE SECTION.
* DL/I function codes
01 DLI-GU PIC X(4) VALUE 'GU '.
01 DLI-GN PIC X(4) VALUE 'GN '.
01 DLI-GNP PIC X(4) VALUE 'GNP '.
01 DLI-GHU PIC X(4) VALUE 'GHU '.
* I/O areas
01 CUSTOMER-SEGMENT.
05 CUST-ID PIC X(10).
05 CUST-NAME PIC X(30).
05 CUST-ADDRESS PIC X(50).
05 CUST-CITY PIC X(20).
05 CUST-STATE PIC X(2).
05 CUST-ZIP PIC X(10).
05 CUST-PHONE PIC X(15).
05 CUST-TYPE PIC X(1).
05 CUST-OPEN-DATE PIC X(10).
05 CUST-STATUS PIC X(1).
01 ACCOUNT-SEGMENT.
05 ACCT-NUMBER PIC X(12).
05 ACCT-TYPE PIC X(2).
05 ACCT-BALANCE PIC S9(11)V99 COMP-3.
05 ACCT-OPEN-DATE PIC X(10).
05 ACCT-STATUS PIC X(1).
05 ACCT-INTEREST-RATE PIC S9(3)V9(4) COMP-3.
* SSAs
01 CUST-UNQUAL-SSA PIC X(9) VALUE 'CUSTOMER '.
01 ACCT-UNQUAL-SSA PIC X(9) VALUE 'ACCOUNT '.
01 CUST-QUAL-SSA.
05 FILLER PIC X(9) VALUE 'CUSTOMER('.
05 FILLER PIC X(10) VALUE 'CUSTID ='.
05 CUST-SSA-KEY PIC X(10) VALUE SPACES.
05 FILLER PIC X(1) VALUE ')'.
* Work fields
01 WS-CUSTOMER-COUNT PIC S9(7) COMP-3 VALUE 0.
01 WS-ACCOUNT-COUNT PIC S9(7) COMP-3 VALUE 0.
01 WS-TOTAL-BALANCE PIC S9(13)V99 COMP-3 VALUE 0.
01 WS-END-OF-DB PIC X(1) VALUE 'N'.
88 END-OF-DATABASE VALUE 'Y'.
88 NOT-END-OF-DATABASE VALUE 'N'.
01 WS-DISPLAY-BALANCE PIC -(12)9.99.
01 WS-DISPLAY-COUNT PIC ZZZ,ZZ9.
* PCB masks in LINKAGE
LINKAGE SECTION.
01 IO-PCB-MASK.
05 IO-LTERM-NAME PIC X(8).
05 FILLER PIC X(2).
05 IO-STATUS-CODE PIC X(2).
05 IO-DATE PIC S9(7) COMP-3.
05 IO-TIME PIC S9(7) COMP-3.
05 IO-MSG-SEQ-NUM PIC S9(7) COMP-3.
05 IO-MOD-NAME PIC X(8).
01 CUST-DB-PCB-MASK.
05 CUST-DBD-NAME PIC X(8).
05 CUST-SEG-LEVEL PIC X(2).
05 CUST-STATUS-CODE PIC X(2).
05 CUST-PROC-OPTIONS PIC X(4).
05 FILLER PIC S9(5) COMP.
05 CUST-SEG-NAME PIC X(8).
05 CUST-KEY-LENGTH PIC S9(5) COMP.
05 CUST-NUM-SENS-SEGS PIC S9(5) COMP.
05 CUST-KEY-FEEDBACK PIC X(30).
PROCEDURE DIVISION USING IO-PCB-MASK
CUST-DB-PCB-MASK.
0000-MAIN-CONTROL.
PERFORM 1000-GU-SINGLE-CUSTOMER
PERFORM 2000-GN-ALL-CUSTOMERS
PERFORM 3000-GNP-ACCOUNTS
GOBACK.
1000-GU-SINGLE-CUSTOMER.
MOVE 'CUST000100' TO CUST-SSA-KEY
CALL 'CBLTDLI' USING DLI-GU
CUST-DB-PCB-MASK
CUSTOMER-SEGMENT
CUST-QUAL-SSA
IF CUST-STATUS-CODE = SPACES
DISPLAY 'Found: ' CUST-NAME
ELSE
DISPLAY 'Not found: ' CUST-STATUS-CODE
END-IF
.
2000-GN-ALL-CUSTOMERS.
MOVE 0 TO WS-CUSTOMER-COUNT
SET NOT-END-OF-DATABASE TO TRUE
PERFORM UNTIL END-OF-DATABASE
CALL 'CBLTDLI' USING DLI-GN
CUST-DB-PCB-MASK
CUSTOMER-SEGMENT
CUST-UNQUAL-SSA
IF CUST-STATUS-CODE = SPACES
ADD 1 TO WS-CUSTOMER-COUNT
ELSE
SET END-OF-DATABASE TO TRUE
END-IF
END-PERFORM
MOVE WS-CUSTOMER-COUNT TO WS-DISPLAY-COUNT
DISPLAY 'Total customers: ' WS-DISPLAY-COUNT
.
3000-GNP-ACCOUNTS.
MOVE 'CUST000100' TO CUST-SSA-KEY
CALL 'CBLTDLI' USING DLI-GU
CUST-DB-PCB-MASK
CUSTOMER-SEGMENT
CUST-QUAL-SSA
IF CUST-STATUS-CODE NOT = SPACES
DISPLAY 'Parent not found'
GO TO 3000-EXIT
END-IF
MOVE 0 TO WS-ACCOUNT-COUNT
MOVE 0 TO WS-TOTAL-BALANCE
SET NOT-END-OF-DATABASE TO TRUE
PERFORM UNTIL END-OF-DATABASE
CALL 'CBLTDLI' USING DLI-GNP
CUST-DB-PCB-MASK
ACCOUNT-SEGMENT
ACCT-UNQUAL-SSA
IF CUST-STATUS-CODE = SPACES
ADD 1 TO WS-ACCOUNT-COUNT
ADD ACCT-BALANCE TO WS-TOTAL-BALANCE
MOVE ACCT-BALANCE TO WS-DISPLAY-BALANCE
DISPLAY ' Acct: ' ACCT-NUMBER
' Bal: ' WS-DISPLAY-BALANCE
ELSE
SET END-OF-DATABASE TO TRUE
END-IF
END-PERFORM
MOVE WS-TOTAL-BALANCE TO WS-DISPLAY-BALANCE
DISPLAY 'Total balance: ' WS-DISPLAY-BALANCE
.
3000-EXIT.
EXIT.
26.9 Complete Example: Updating an IMS Database
This program demonstrates ISRT, REPL, and DLET calls. It inserts a new customer with an account and a transaction, updates the customer address, applies a deposit to the account balance, and deletes a transaction. This corresponds to example-02-ims-db-update.cob.
*================================================================*
* IMS DB UPDATE OPERATIONS - COMPLETE EXAMPLE *
* Demonstrates: ISRT, REPL, DLET calls *
* [IBM Enterprise COBOL] - IMS DL/I interface *
*================================================================*
IDENTIFICATION DIVISION.
PROGRAM-ID. IMSUPD1.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 DLI-GHU PIC X(4) VALUE 'GHU '.
01 DLI-GU PIC X(4) VALUE 'GU '.
01 DLI-GHNP PIC X(4) VALUE 'GHNP'.
01 DLI-ISRT PIC X(4) VALUE 'ISRT'.
01 DLI-REPL PIC X(4) VALUE 'REPL'.
01 DLI-DLET PIC X(4) VALUE 'DLET'.
01 CUSTOMER-SEGMENT.
05 CUST-ID PIC X(10).
05 CUST-NAME PIC X(30).
05 CUST-ADDRESS PIC X(50).
05 CUST-CITY PIC X(20).
05 CUST-STATE PIC X(2).
05 CUST-ZIP PIC X(10).
05 CUST-PHONE PIC X(15).
05 CUST-TYPE PIC X(1).
05 CUST-OPEN-DATE PIC X(10).
05 CUST-STATUS PIC X(1).
01 ACCOUNT-SEGMENT.
05 ACCT-NUMBER PIC X(12).
05 ACCT-TYPE PIC X(2).
05 ACCT-BALANCE PIC S9(11)V99 COMP-3.
05 ACCT-OPEN-DATE PIC X(10).
05 ACCT-STATUS PIC X(1).
05 ACCT-INTEREST-RATE PIC S9(3)V9(4) COMP-3.
01 CUST-UNQUAL-SSA PIC X(9) VALUE 'CUSTOMER '.
01 ACCT-UNQUAL-SSA PIC X(9) VALUE 'ACCOUNT '.
01 TRAN-UNQUAL-SSA PIC X(9) VALUE 'TRANSACT '.
01 CUST-QUAL-SSA.
05 FILLER PIC X(9) VALUE 'CUSTOMER('.
05 FILLER PIC X(10) VALUE 'CUSTID ='.
05 CUST-SSA-KEY PIC X(10) VALUE SPACES.
05 FILLER PIC X(1) VALUE ')'.
01 ACCT-QUAL-SSA.
05 FILLER PIC X(9) VALUE 'ACCOUNT ('.
05 FILLER PIC X(10) VALUE 'ACCTNO ='.
05 ACCT-SSA-KEY PIC X(12) VALUE SPACES.
05 FILLER PIC X(1) VALUE ')'.
01 WS-DISPLAY-BALANCE PIC -(12)9.99.
LINKAGE SECTION.
01 IO-PCB-MASK.
05 FILLER PIC X(10).
05 IO-STATUS-CODE PIC X(2).
05 FILLER PIC X(20).
01 CUST-DB-PCB-MASK.
05 CUST-DBD-NAME PIC X(8).
05 CUST-SEG-LEVEL PIC X(2).
05 CUST-STATUS-CODE PIC X(2).
05 CUST-PROC-OPTIONS PIC X(4).
05 FILLER PIC S9(5) COMP.
05 CUST-SEG-NAME PIC X(8).
05 CUST-KEY-LENGTH PIC S9(5) COMP.
05 CUST-NUM-SENS-SEGS PIC S9(5) COMP.
05 CUST-KEY-FEEDBACK PIC X(30).
PROCEDURE DIVISION USING IO-PCB-MASK
CUST-DB-PCB-MASK.
0000-MAIN-CONTROL.
PERFORM 1000-INSERT-CUSTOMER
PERFORM 2000-INSERT-ACCOUNT
PERFORM 3000-UPDATE-ADDRESS
PERFORM 4000-UPDATE-BALANCE
GOBACK.
1000-INSERT-CUSTOMER.
INITIALIZE CUSTOMER-SEGMENT
MOVE 'CUST000999' TO CUST-ID
MOVE 'JOHNSON, ROBERT A' TO CUST-NAME
MOVE '1234 OAK AVENUE' TO CUST-ADDRESS
MOVE 'CHICAGO' TO CUST-CITY
MOVE 'IL' TO CUST-STATE
MOVE '60601' TO CUST-ZIP
MOVE 'I' TO CUST-TYPE
MOVE 'A' TO CUST-STATUS
CALL 'CBLTDLI' USING DLI-ISRT
CUST-DB-PCB-MASK
CUSTOMER-SEGMENT
CUST-UNQUAL-SSA
IF CUST-STATUS-CODE = SPACES
DISPLAY 'Customer inserted: ' CUST-ID
ELSE
DISPLAY 'ISRT error: ' CUST-STATUS-CODE
END-IF
.
2000-INSERT-ACCOUNT.
MOVE 'CUST000999' TO CUST-SSA-KEY
INITIALIZE ACCOUNT-SEGMENT
MOVE '999000000001' TO ACCT-NUMBER
MOVE 'CK' TO ACCT-TYPE
MOVE 1500.00 TO ACCT-BALANCE
MOVE 'A' TO ACCT-STATUS
MOVE 0.0025 TO ACCT-INTEREST-RATE
CALL 'CBLTDLI' USING DLI-ISRT
CUST-DB-PCB-MASK
ACCOUNT-SEGMENT
CUST-QUAL-SSA
ACCT-UNQUAL-SSA
IF CUST-STATUS-CODE = SPACES
DISPLAY 'Account inserted: ' ACCT-NUMBER
END-IF
.
3000-UPDATE-ADDRESS.
MOVE 'CUST000999' TO CUST-SSA-KEY
CALL 'CBLTDLI' USING DLI-GHU
CUST-DB-PCB-MASK
CUSTOMER-SEGMENT
CUST-QUAL-SSA
IF CUST-STATUS-CODE NOT = SPACES
GO TO 3000-EXIT
END-IF
* Modify non-key fields only
MOVE '5678 MAPLE BOULEVARD' TO CUST-ADDRESS
MOVE 'EVANSTON' TO CUST-CITY
MOVE '60201' TO CUST-ZIP
CALL 'CBLTDLI' USING DLI-REPL
CUST-DB-PCB-MASK
CUSTOMER-SEGMENT
IF CUST-STATUS-CODE = SPACES
DISPLAY 'Address updated for ' CUST-ID
END-IF
.
3000-EXIT.
EXIT.
4000-UPDATE-BALANCE.
MOVE 'CUST000999' TO CUST-SSA-KEY
MOVE '999000000001' TO ACCT-SSA-KEY
CALL 'CBLTDLI' USING DLI-GHU
CUST-DB-PCB-MASK
ACCOUNT-SEGMENT
CUST-QUAL-SSA
ACCT-QUAL-SSA
IF CUST-STATUS-CODE NOT = SPACES
GO TO 4000-EXIT
END-IF
ADD 250.00 TO ACCT-BALANCE
CALL 'CBLTDLI' USING DLI-REPL
CUST-DB-PCB-MASK
ACCOUNT-SEGMENT
IF CUST-STATUS-CODE = SPACES
MOVE ACCT-BALANCE TO WS-DISPLAY-BALANCE
DISPLAY 'New balance: ' WS-DISPLAY-BALANCE
END-IF
.
4000-EXIT.
EXIT.
26.10 IMS Transaction Manager (IMS TM/DC)
Online Transaction Processing with IMS
IMS is not just a database -- it is also a full online transaction processing system. IMS TM (Transaction Manager), also called IMS DC (Data Communications), performs the same role for IMS applications that CICS performs for CICS applications: it manages terminals, queues messages, schedules programs, and provides recovery services.
How IMS TM Works
The flow of an IMS online transaction follows this sequence:
- A terminal user types a transaction code and data on a 3270 terminal (e.g.,
ACCTINQ INQ CUST000100) and presses Enter. - IMS TM receives the message and places it in the message queue.
- IMS TM schedules an MPP (Message Processing Program) associated with that transaction code.
- The MPP reads the input message from the queue using a GU call with the IO PCB.
- The MPP accesses one or more IMS databases using DL/I calls with DB PCBs.
- The MPP sends the response back to the terminal using an ISRT call with the IO PCB.
- IMS TM delivers the output message to the terminal.
MPP -- Message Processing Program
An MPP is the IMS equivalent of a CICS transaction program. It processes messages from the IMS message queue. The key differences from a batch IMS program are:
- The MPP reads input messages with
GU IO-PCB-MASK INPUT-MESSAGE. - The MPP sends output messages with
ISRT IO-PCB-MASK OUTPUT-MESSAGE. - The MPP loops, processing messages until the queue is empty (status code
QC). - The MPP does not open files or define the ENVIRONMENT DIVISION for I/O.
Message Format
IMS messages have a specific format. Each message segment begins with a 4-byte prefix:
01 INPUT-MESSAGE.
05 IN-LL PIC S9(4) COMP.
05 IN-ZZ PIC S9(4) COMP.
05 IN-TRAN-CODE PIC X(8).
05 IN-DATA PIC X(100).
- LL: The total length of this message segment (including LL and ZZ).
- ZZ: Reserved, always zero.
- TRAN-CODE: The transaction code typed by the user (e.g., ACCTINQ).
- DATA: The rest of the user's input.
Output messages use the same LL/ZZ prefix:
01 OUTPUT-MSG-HEADER.
05 OUT-HDR-LL PIC S9(4) COMP VALUE +80.
05 OUT-HDR-ZZ PIC S9(4) COMP VALUE +0.
05 OUT-HDR-LINE PIC X(76).
Complete MPP Example
The following program implements an account inquiry transaction. When a bank teller types ACCTINQ INQ CUST000100, the program looks up the customer, retrieves all accounts, and sends a formatted response back to the terminal. This corresponds to example-04-ims-tm.cob.
*================================================================*
* IMS MPP - ACCOUNT INQUIRY TRANSACTION *
* Transaction code: ACCTINQ *
* Functions: INQ (full inquiry), BAL (balance only) *
* [IBM Enterprise COBOL] - IMS TM/DC interface *
*================================================================*
IDENTIFICATION DIVISION.
PROGRAM-ID. IMSTM01.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 DLI-GU PIC X(4) VALUE 'GU '.
01 DLI-GNP PIC X(4) VALUE 'GNP '.
01 DLI-ISRT PIC X(4) VALUE 'ISRT'.
* Input message area
01 INPUT-MESSAGE.
05 IN-LL PIC S9(4) COMP.
05 IN-ZZ PIC S9(4) COMP.
05 IN-TRAN-CODE PIC X(8).
05 IN-DATA PIC X(100).
01 INPUT-FIELDS.
05 IN-FUNCTION PIC X(3).
88 FUNC-INQUIRY VALUE 'INQ'.
88 FUNC-BALANCE VALUE 'BAL'.
05 IN-CUSTOMER-ID PIC X(10).
* Output message area
01 OUTPUT-MSG.
05 OUT-LL PIC S9(4) COMP VALUE +80.
05 OUT-ZZ PIC S9(4) COMP VALUE +0.
05 OUT-LINE PIC X(76).
* Database segments and SSAs
01 CUSTOMER-SEGMENT.
05 CUST-ID PIC X(10).
05 CUST-NAME PIC X(30).
05 CUST-ADDRESS PIC X(50).
05 CUST-CITY PIC X(20).
05 CUST-STATE PIC X(2).
05 CUST-ZIP PIC X(10).
05 CUST-PHONE PIC X(15).
05 CUST-TYPE PIC X(1).
05 CUST-OPEN-DATE PIC X(10).
05 CUST-STATUS PIC X(1).
01 ACCOUNT-SEGMENT.
05 ACCT-NUMBER PIC X(12).
05 ACCT-TYPE PIC X(2).
05 ACCT-BALANCE PIC S9(11)V99 COMP-3.
05 ACCT-OPEN-DATE PIC X(10).
05 ACCT-STATUS PIC X(1).
05 ACCT-INTEREST-RATE PIC S9(3)V9(4) COMP-3.
01 CUST-QUAL-SSA.
05 FILLER PIC X(9) VALUE 'CUSTOMER('.
05 FILLER PIC X(10) VALUE 'CUSTID ='.
05 CUST-SSA-KEY PIC X(10) VALUE SPACES.
05 FILLER PIC X(1) VALUE ')'.
01 ACCT-UNQUAL-SSA PIC X(9) VALUE 'ACCOUNT '.
01 WS-DISPLAY-BALANCE PIC $$$,$$$,$$9.99-.
01 WS-TOTAL-BALANCE PIC S9(13)V99 COMP-3 VALUE 0.
01 WS-MORE-MESSAGES PIC X(1) VALUE 'Y'.
88 MESSAGES-AVAILABLE VALUE 'Y'.
88 NO-MORE-MESSAGES VALUE 'N'.
01 WS-END-ACCT PIC X(1) VALUE 'N'.
88 END-OF-ACCOUNTS VALUE 'Y'.
88 MORE-ACCOUNTS VALUE 'N'.
LINKAGE SECTION.
01 IO-PCB-MASK.
05 IO-LTERM-NAME PIC X(8).
05 FILLER PIC X(2).
05 IO-STATUS-CODE PIC X(2).
05 FILLER PIC X(20).
01 CUST-DB-PCB.
05 CUST-DBD-NAME PIC X(8).
05 CUST-SEG-LEVEL PIC X(2).
05 CUST-STATUS-CODE PIC X(2).
05 CUST-PROC-OPTIONS PIC X(4).
05 FILLER PIC S9(5) COMP.
05 CUST-SEG-NAME PIC X(8).
05 CUST-KEY-LENGTH PIC S9(5) COMP.
05 CUST-NUM-SENS-SEGS PIC S9(5) COMP.
05 CUST-KEY-FEEDBACK PIC X(30).
PROCEDURE DIVISION USING IO-PCB-MASK
CUST-DB-PCB.
0000-MAIN-CONTROL.
* MPP message processing loop
PERFORM 1000-GET-MESSAGE
PERFORM UNTIL NO-MORE-MESSAGES
PERFORM 2000-PROCESS-INQUIRY
PERFORM 1000-GET-MESSAGE
END-PERFORM
GOBACK.
1000-GET-MESSAGE.
INITIALIZE INPUT-MESSAGE
* GU with IO PCB reads next message from queue
CALL 'CBLTDLI' USING DLI-GU
IO-PCB-MASK
INPUT-MESSAGE
IF IO-STATUS-CODE = SPACES
SET MESSAGES-AVAILABLE TO TRUE
ELSE
SET NO-MORE-MESSAGES TO TRUE
END-IF
.
2000-PROCESS-INQUIRY.
UNSTRING IN-DATA DELIMITED BY SPACES
INTO IN-FUNCTION IN-CUSTOMER-ID
END-UNSTRING
MOVE IN-CUSTOMER-ID TO CUST-SSA-KEY
CALL 'CBLTDLI' USING DLI-GU
CUST-DB-PCB
CUSTOMER-SEGMENT
CUST-QUAL-SSA
IF CUST-STATUS-CODE NOT = SPACES
MOVE SPACES TO OUT-LINE
STRING 'CUSTOMER NOT FOUND: ' IN-CUSTOMER-ID
DELIMITED BY SIZE INTO OUT-LINE
CALL 'CBLTDLI' USING DLI-ISRT
IO-PCB-MASK
OUTPUT-MSG
GO TO 2000-EXIT
END-IF
* Send customer info to terminal
MOVE SPACES TO OUT-LINE
STRING 'NAME: ' CUST-NAME
DELIMITED BY SIZE INTO OUT-LINE
CALL 'CBLTDLI' USING DLI-ISRT
IO-PCB-MASK OUTPUT-MSG
* Read and display accounts
MOVE 0 TO WS-TOTAL-BALANCE
SET MORE-ACCOUNTS TO TRUE
PERFORM UNTIL END-OF-ACCOUNTS
CALL 'CBLTDLI' USING DLI-GNP
CUST-DB-PCB
ACCOUNT-SEGMENT
ACCT-UNQUAL-SSA
IF CUST-STATUS-CODE = SPACES
ADD ACCT-BALANCE TO WS-TOTAL-BALANCE
MOVE ACCT-BALANCE TO WS-DISPLAY-BALANCE
MOVE SPACES TO OUT-LINE
STRING 'ACCT: ' ACCT-NUMBER
' TYPE: ' ACCT-TYPE
' BAL: ' WS-DISPLAY-BALANCE
DELIMITED BY SIZE INTO OUT-LINE
CALL 'CBLTDLI' USING DLI-ISRT
IO-PCB-MASK
OUTPUT-MSG
ELSE
SET END-OF-ACCOUNTS TO TRUE
END-IF
END-PERFORM
MOVE WS-TOTAL-BALANCE TO WS-DISPLAY-BALANCE
MOVE SPACES TO OUT-LINE
STRING 'TOTAL: ' WS-DISPLAY-BALANCE
DELIMITED BY SIZE INTO OUT-LINE
CALL 'CBLTDLI' USING DLI-ISRT
IO-PCB-MASK OUTPUT-MSG
.
2000-EXIT.
EXIT.
Notice the two distinct uses of DL/I calls: GU IO-PCB-MASK reads from the message queue (terminal input), while GU CUST-DB-PCB reads from the database. ISRT IO-PCB-MASK sends output to the terminal. The PCB parameter determines whether the call goes to the message queue or the database.
26.11 MPP vs. BMP Regions
IMS runs application programs in different types of regions:
| Region Type | Full Name | Description |
|---|---|---|
| MPP | Message Processing Program | Online region that processes messages from the IMS message queue. Handles interactive terminal transactions. Short-running. |
| BMP | Batch Message Processing | Batch region that has access to IMS databases while the online system is running. Long-running batch jobs that share databases with MPP regions. |
| IFP | IMS Fast Path | High-performance online region for very high-volume, short transactions using Fast Path DEDBs. |
| Batch DL/I | Batch Data Language/I | Batch region that runs when the IMS online system is shut down. Exclusive access to databases for utilities, reorganization, and bulk processing. |
MPP Characteristics
- Processes messages from the message queue.
- Short-running: processes one message (or a set of messages), then returns.
- Scheduled by IMS when messages arrive.
- Uses the IO PCB for terminal communication.
- Commits work after each message (automatic sync point).
BMP Characteristics
- Runs as a batch job (submitted through JCL) but accesses IMS databases.
- Can run concurrently with the online system, sharing databases with MPP regions.
- Long-running: processes all records in a sequential pass.
- Should issue periodic checkpoints (CHKP) to commit work and enable restart.
- Uses the IO PCB for checkpoints and status, but typically not for terminal I/O.
- The JCL invokes DFSRRC00, the IMS region controller, rather than calling the application program directly.
26.12 Checkpoint and Restart
Why Checkpoint/Restart Matters
Long-running batch IMS programs (BMPs) may process millions of database records. If the program fails after processing 800,000 records, you do not want to start over from the beginning. IMS provides checkpoint/restart to solve this problem.
A checkpoint (CHKP call) does three things: 1. Commits all database changes since the last checkpoint. 2. Saves a snapshot of application data (your counters, positions, and flags) so they can be restored on restart. 3. Writes a log record that marks the recovery point.
An extended restart (XRST call) at the beginning of the program checks whether a prior checkpoint exists from a failed run. If so, it restores the saved application data and repositions the database so processing can resume from the last checkpoint.
The CHKP Call
* Checkpoint data area - saved and restored
01 WS-CHKP-DATA.
05 CHKP-LAST-CUST-ID PIC X(10) VALUE SPACES.
05 CHKP-CUST-COUNT PIC S9(7) COMP-3 VALUE 0.
05 CHKP-ACCT-COUNT PIC S9(7) COMP-3 VALUE 0.
05 CHKP-UPD-COUNT PIC S9(7) COMP-3 VALUE 0.
05 CHKP-RECORDS-SINCE PIC S9(7) COMP-3 VALUE 0.
05 FILLER PIC X(154) VALUE SPACES.
01 WS-CHKP-AREA-LENGTH PIC S9(8) COMP VALUE +200.
01 WS-CHKP-ID PIC X(8) VALUE SPACES.
01 WS-CHKP-SEQ PIC 9(6) VALUE 0.
Issue the CHKP call periodically (e.g., every 500 records):
7000-TAKE-CHECKPOINT.
* Generate a unique checkpoint ID
ADD 1 TO WS-CHKP-SEQ
STRING 'INTCL' WS-CHKP-SEQ
DELIMITED BY SIZE INTO WS-CHKP-ID
END-STRING
* Issue the symbolic checkpoint
CALL 'CBLTDLI' USING DLI-CHKP
IO-PCB-MASK
WS-CHKP-DATA
WS-CHKP-AREA-LENGTH
WS-CHKP-ID
IF IO-STATUS-CODE = SPACES
DISPLAY 'CHECKPOINT ' WS-CHKP-ID ' TAKEN'
MOVE 0 TO CHKP-RECORDS-SINCE
ELSE
DISPLAY 'CHECKPOINT ERROR: ' IO-STATUS-CODE
END-IF
.
The CHKP call parameters are: 1. DLI-CHKP: The function code for checkpoint. 2. IO-PCB-MASK: Always the IO PCB for system calls. 3. WS-CHKP-DATA: The application data area to be saved. 4. WS-CHKP-AREA-LENGTH: The length of the data area. 5. WS-CHKP-ID: An 8-byte identifier for this checkpoint.
The XRST Call
Issue the XRST call at the very beginning of the program, before any database processing:
1500-CHECK-RESTART.
CALL 'CBLTDLI' USING DLI-XRST
IO-PCB-MASK
WS-CHKP-DATA
WS-CHKP-AREA-LENGTH
WS-CHKP-ID
IF IO-STATUS-CODE = SPACES
IF WS-CHKP-ID NOT = SPACES
* Restart: data area has been restored
DISPLAY 'RESTARTING FROM: ' WS-CHKP-ID
DISPLAY 'LAST CUSTOMER: '
CHKP-LAST-CUST-ID
ELSE
* Fresh start: no prior checkpoint
DISPLAY 'FRESH START'
INITIALIZE WS-CHKP-DATA
END-IF
ELSE
DISPLAY 'XRST ERROR: ' IO-STATUS-CODE
GOBACK
END-IF
.
If XRST finds a prior checkpoint, it restores WS-CHKP-DATA to the values it held at the last successful CHKP call. The database position is also restored automatically. Your program can then resume from where it left off -- the counters, flags, and last-processed key are all intact.
Checkpoint Interval
Choose a checkpoint interval that balances recovery time against overhead. Common intervals are every 500 to 5,000 records. More frequent checkpoints mean less work is lost on failure but add I/O overhead. Less frequent checkpoints are more efficient but risk more rework on restart. For critical financial batch jobs, 500 records is typical.
26.13 JCL for IMS Batch Programs
The IMS Region Controller: DFSRRC00
IMS batch programs (BMPs and Batch DL/I) are not invoked directly. Instead, JCL executes DFSRRC00, the IMS region controller. DFSRRC00 initializes the IMS environment, loads the PSB, invokes your application program, and manages checkpoint/restart.
Complete JCL Example
The following JCL runs the interest calculation BMP program (example-05-ims-batch.jcl):
//INTCALC JOB (ACCT),'INTEREST CALC',
// CLASS=A,MSGCLASS=X,MSGLEVEL=(1,1),
// NOTIFY=&SYSUID,REGION=0M
//*================================================================*
//* JCL FOR IMS BMP EXECUTION *
//*================================================================*
//*
//STEP01 EXEC PGM=DFSRRC00,
// PARM=(BMP,IMSBMP01,IMSBMP01,,,,,,,,,,,Y,N,,,,,,,,,,,'')
//*
//* PARM explanation:
//* BMP - Region type
//* IMSBMP01 - Application program name (load module)
//* IMSBMP01 - PSB name
//* Y - Checkpoint/restart indicator
//* N - Not conversational
//*
//*----------------------------------------------------------------*
//* LOAD LIBRARIES *
//*----------------------------------------------------------------*
//STEPLIB DD DSN=IMS.SDFSRESL,DISP=SHR
// DD DSN=APPL.LOADLIB,DISP=SHR
//*
//*----------------------------------------------------------------*
//* IMS SYSTEM LIBRARIES *
//*----------------------------------------------------------------*
//DFSRESLB DD DSN=IMS.SDFSRESL,DISP=SHR
//IMS DD DSN=IMS.DBDLIB,DISP=SHR
// DD DSN=IMS.PSBLIB,DISP=SHR
//*
//*----------------------------------------------------------------*
//* IMS LOG DATASET (critical for recovery) *
//*----------------------------------------------------------------*
//IEFRDER DD DSN=IMS.LOG.INTCALC.PRIMARY,
// DISP=(NEW,CATLG,CATLG),
// UNIT=SYSDA,
// SPACE=(CYL,(50,10),RLSE),
// DCB=(RECFM=VB,LRECL=6136,BLKSIZE=6144)
//*
//IEFRDER2 DD DSN=IMS.LOG.INTCALC.SECOND,
// DISP=(NEW,CATLG,CATLG),
// UNIT=SYSDA,
// SPACE=(CYL,(50,10),RLSE),
// DCB=(RECFM=VB,LRECL=6136,BLKSIZE=6144)
//*
//*----------------------------------------------------------------*
//* VSAM BUFFER POOL DEFINITIONS *
//*----------------------------------------------------------------*
//DFSVSAMP DD *
4096,10
IOBF=(4096,10)
IOBF=(2048,5)
LOCKMAX=500
/*
//*
//*----------------------------------------------------------------*
//* DATABASE DD STATEMENTS *
//*----------------------------------------------------------------*
//CUSTDB DD DSN=IMS.DB.CUSTOMER.DATA,DISP=SHR
//CUSTDBI DD DSN=IMS.DB.CUSTOMER.INDEX,DISP=SHR
//CUSTDBO DD DSN=IMS.DB.CUSTOMER.OVFL,DISP=SHR
//*
//*----------------------------------------------------------------*
//* APPLICATION OUTPUT FILES *
//*----------------------------------------------------------------*
//RPTFILE DD DSN=APPL.INTCALC.REPORT,
// DISP=(NEW,CATLG,DELETE),
// UNIT=SYSDA,
// SPACE=(TRK,(50,10),RLSE),
// DCB=(RECFM=FB,LRECL=132,BLKSIZE=0)
//*
//SYSPRINT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//SYSOUT DD SYSOUT=*
Key DD Statements Explained
| DD Name | Purpose |
|---|---|
| STEPLIB | Contains the IMS RESLIB (IMS runtime modules) and the application load library (your compiled program). |
| DFSRESLB | IMS resident library, used by the region controller. |
| IMS | Concatenation of DBDLIB (database definitions) and PSBLIB (program specifications). |
| IEFRDER / IEFRDER2 | IMS log datasets. Primary and secondary. Critical for recovery and restart. |
| DFSVSAMP | VSAM buffer pool definitions. Controls I/O buffer sizes and counts for database access performance. |
| CUSTDB, CUSTDBI, CUSTDBO | Database DD statements. Each physical database referenced by the PSB needs DD statements for its VSAM clusters (data, index, overflow). |
| RPTFILE | Application-specific output file (not IMS-specific). |
DFSRRC00 Return Codes
| RC | Meaning |
|---|---|
| 0 | Successful completion |
| 4 | Warning (check IMS log for details) |
| 8 | Application error |
| 12 | Severe error |
| 16 | IMS system error |
Restart After Failure
To restart a failed BMP after a checkpoint:
- Resubmit the same JCL (the IMS log from the failed run must still exist).
- DFSRRC00 detects the prior checkpoint from the log.
- The XRST call in your program restores the saved data area.
- Your program resumes processing from the last checkpoint.
This is one of IMS's most powerful features for production batch processing. A job that fails at 3 AM after processing 2 million records out of 5 million does not need to reprocess those 2 million records. It restarts from the last checkpoint and processes only the remaining records.
26.14 Hierarchical Database Navigation Patterns
Full Hierarchy Traversal
A common requirement is to traverse an entire database record -- the root and all its descendants at every level. The pattern uses GU to position to the root, then nested GNP loops for each level:
* Position to the root customer
MOVE 'CUST000100' TO CUST-SSA-KEY
CALL 'CBLTDLI' USING DLI-GU
CUST-PCB
CUSTOMER-IO-AREA
CUST-QUAL-SSA
IF CUST-STATUS-CODE NOT = SPACES
GO TO 2000-EXIT
END-IF
DISPLAY 'CUSTOMER: ' CUST-ID ' - ' CUST-NAME
* Read all ACCOUNT children
SET MORE-CHILDREN TO TRUE
PERFORM UNTIL END-OF-CHILDREN
CALL 'CBLTDLI' USING DLI-GNP
CUST-PCB
ACCOUNT-IO-AREA
ACCT-UNQUAL-SSA
IF CUST-STATUS-CODE = SPACES
DISPLAY ' ACCOUNT: ' ACCT-NUMBER
* For each account, read its transactions
PERFORM 2100-READ-TRANSACTIONS
ELSE
SET END-OF-CHILDREN TO TRUE
END-IF
END-PERFORM
The challenge in multi-level traversal is that reading child segments at one level can affect the position at higher levels. After reading transactions under the first account, you may need to re-establish position to continue reading the next account. The code examples demonstrate this pattern in detail.
Cross-Database Operations
When your program accesses multiple databases (through multiple PCBs), each PCB maintains its own independent database position. This allows you to look up a customer in the CUSTOMER database and then find that customer's orders in a separate ORDER database without losing position in either:
* Look up customer in CUSTOMER database
CALL 'CBLTDLI' USING DLI-GU
CUST-PCB
CUSTOMER-IO-AREA
CUST-QUAL-SSA
* Look up orders in ORDER database (separate PCB)
MOVE CUST-ID TO ORDR-SSA-CUST
CALL 'CBLTDLI' USING DLI-GN
ORDER-PCB
ORDER-IO-AREA
ORDR-CUST-SSA
The CUST-PCB and ORDER-PCB maintain separate positions. Calls against ORDER-PCB do not disturb the position in the CUSTOMER database.
Efficient Navigation with Path Calls
Instead of issuing multiple GU and GNP calls to navigate to a deeply nested segment, use a single GU with SSAs at each level:
* INEFFICIENT: Three separate calls
* Call 1: GU CUSTOMER (root)
* Call 2: GNP ACCOUNT (child)
* Call 3: GNP TRANSACTION (grandchild)
* EFFICIENT: Single path call
MOVE 'CUST000100' TO CUST-D-KEY
CALL 'CBLTDLI' USING DLI-GU
CUST-PCB
TRANSACTION-IO-AREA
CUST-PATH-D-SSA
ACCT-UNQUAL-SSA
TRAN-UNQUAL-SSA
The D command code on the customer SSA tells IMS to include the customer segment in the path traversal. A single GU call navigates the entire hierarchy from root to the transaction level, reducing the number of DL/I calls and improving performance.
26.15 IMS-COBOL Integration Patterns
Pattern 1: Batch Sequential Processing
Process all records sequentially with checkpoints:
XRST (check for restart)
GN loop reading root segments
GNP loop reading children
Process / Update
End GNP loop
Checkpoint every N records
End GN loop
Final CHKP
Pattern 2: Online Inquiry (MPP)
Non-conversational inquiry transaction:
GU IO-PCB (read input message)
Parse input
GU DB-PCB (look up root segment)
GNP DB-PCB loop (read children)
ISRT IO-PCB (send each output line)
End loop
ISRT IO-PCB (send summary)
GOBACK
Pattern 3: Online Update (MPP)
Non-conversational update transaction:
GU IO-PCB (read input message)
Parse input
GHU DB-PCB (retrieve segment with hold)
Validate data
Modify non-key fields
REPL DB-PCB (update the segment)
ISRT IO-PCB (send confirmation)
GOBACK
Pattern 4: Lookup Across Databases
Cross-reference between related databases:
GU CUST-PCB (find customer)
Save CUST-ID
GN ORDER-PCB with SSA on CUST-ID (find orders)
Loop:
GNP ORDER-PCB (read order lines)
End loop
Common Mistakes to Avoid
-
Forgetting the hold call before REPL/DLET. Status code DJ is the telltale sign. Always use GHU/GHN/GHNP before REPL or DLET.
-
Changing the key field before REPL. Status code DA. The key field identifies the segment's position in the hierarchy. Changing it would corrupt the database structure.
-
Using the wrong PCB for a call. If you pass the IO PCB instead of the DB PCB, IMS interprets the call as a message operation, not a database operation. This can produce unexpected results or abends.
-
Not checking status codes after every call. A single unchecked error can cascade through the rest of the program. Always check the status code in the PCB after every CALL 'CBLTDLI'.
-
SSA field name mismatch. The field name in the SSA must match the field name defined in the DBD, not the COBOL field name in your program. These are frequently different (e.g., DBD field CUSTID vs. COBOL field CUST-ID).
-
I/O area size mismatch. If your COBOL I/O area is shorter than the actual segment, data can be truncated. If it is longer, you may read garbage beyond the segment end. Match the segment definition exactly.
-
Losing database position. After a GU call to re-position, the current position at all lower levels is reset. Be aware of how each call affects position.
26.16 Hands-On Practice with IBM Z Xplore
[IBM Enterprise COBOL] Since IMS runs exclusively on IBM z/OS, you cannot install it on a personal computer or run IMS programs under GnuCOBOL. However, IBM provides free access to a real mainframe through the IBM Z Xplore program (formerly known as IBM Z Open Education and Master the Mainframe).
Getting Started with Z Xplore
- Visit the IBM Z Xplore website at https://www.ibm.com/z/resources/zxplore.
- Create a free IBM ID if you do not already have one.
- Register for the Z Xplore learning paths.
- You will receive credentials for a real z/OS system accessible via a 3270 terminal emulator or SSH.
What You Can Practice
The Z Xplore environment includes: - TSO/ISPF for editing datasets and submitting JCL. - COBOL compiler (IBM Enterprise COBOL) for compiling programs. - IMS resources (depending on the learning path) for running DL/I programs. - JCL submission for executing batch jobs. - SDSF for viewing job output and logs.
Alternative Learning Resources
If direct IMS access is not available through Z Xplore at the time you are reading this, consider these alternatives:
- IBM IMS documentation: The IBM Knowledge Center provides comprehensive IMS documentation including the Application Programming Guide, which covers all DL/I calls with examples.
- IBM Redbooks: Several IBM Redbooks cover IMS programming in detail, including "IMS Primer" (SG24-5352) and "IMS Application Programming" (SC18-9698).
- Desk-checking: You can write IMS COBOL programs on any system and desk-check them against the status code tables and call formats in this chapter. Understanding the call interface conceptually is valuable even without a running IMS system.
26.17 IMS in Modern Architectures
IMS databases do not exist in isolation. Modern enterprises connect IMS to contemporary systems through several integration technologies:
IMS Connect
IMS Connect provides TCP/IP access to IMS transactions. Java applications, web services, and REST APIs can send messages to IMS transactions through IMS Connect, allowing IMS data and business logic to participate in modern architectures without modifying the COBOL programs.
IMS Open Database
IMS Open Database allows non-COBOL applications to access IMS databases directly using standard SQL or a JDBC/ODBC interface. Java programs can issue SQL queries against IMS hierarchical databases through the IMS Universal Drivers.
IMS and MQ
IBM MQ (formerly WebSphere MQ) can queue messages for IMS transactions, enabling asynchronous integration with other systems. A web application can place a message on an MQ queue, and IMS picks it up for processing -- decoupling the front-end from the back-end.
IMS and DB2
Many enterprises maintain both IMS and DB2 databases. A single COBOL program can access both -- using DL/I calls for IMS and EXEC SQL for DB2 -- within the same transaction. This is common in banks where the core deposit system is on IMS but regulatory reporting goes through DB2.
What You Have Learned
This chapter covered IMS database and transaction management from the COBOL programmer's perspective. Here is a summary of the key concepts:
The Hierarchical Data Model: - IMS stores data in tree structures (hierarchies) where each segment has one parent and may have multiple children. - The root segment sits at the top. Child segments depend on their parents and cannot exist independently. - A database record is one root segment together with all its descendants. - IMS traverses hierarchies in depth-first, left-to-right order (hierarchical sequence).
The DL/I Call Interface:
- COBOL programs communicate with IMS through CALL 'CBLTDLI' -- the DL/I call interface.
- Every call takes a function code, a PCB mask, an I/O area, and optional Segment Search Arguments (SSAs).
- Function codes are 4-byte values: GU, GN, GNP, GHU, GHN, GHNP, ISRT, REPL, DLET, CHKP, XRST.
PCBs and PSBs: - The PSB defines a program's authorized view of IMS databases. - Each PCB represents one database view or the IO PCB for message/system calls. - PCBs are received through the PROCEDURE DIVISION USING clause, with the IO PCB always first. - The status code in the PCB tells you the result of every DL/I call.
Segment Search Arguments (SSAs): - Unqualified SSAs specify a segment type name only (9 bytes). - Qualified SSAs add search conditions with field names, operators, and values. - Boolean SSAs combine conditions with AND (*) or OR (+). - Command codes (D, F, L, N, P, U) modify call behavior for path calls, first/last access, and position management.
Database Calls: - GU (Get Unique): Direct access by key -- random access to any segment. - GN (Get Next): Sequential forward retrieval in hierarchical sequence. - GNP (Get Next within Parent): Retrieves children within a parent scope. - GHU/GHN/GHNP: Hold variants that lock the segment for subsequent update or delete. - ISRT: Inserts a new segment. Root segments need an unqualified SSA. Child segments need parent path SSAs. - REPL: Updates a held segment. Must not change the key field. - DLET: Deletes a held segment and all its descendants (cascade delete).
Status Codes: - Spaces = success. GE = not found. GB = end of database. II = duplicate on insert. - DA = key field changed. DJ = no prior hold call. QC = no more messages. - Always check the status code after every DL/I call.
IMS Transaction Manager (IMS TM): - IMS TM manages online transaction processing with terminals, message queues, and program scheduling. - MPP (Message Processing Program) processes messages from the queue. - GU IO-PCB reads input messages. ISRT IO-PCB sends output messages. - MPPs loop until status code QC indicates no more messages.
MPP vs. BMP Regions: - MPP: Online, short-running, processes messages from the queue. - BMP: Batch, long-running, accesses IMS databases while the online system runs. - Batch DL/I: Batch with exclusive database access (online system not running).
Checkpoint/Restart: - CHKP commits database changes and saves application state for recovery. - XRST at program start checks for a prior checkpoint and restores state on restart. - Checkpoint intervals of 500-5,000 records balance recovery time and overhead. - Restart resubmits the same JCL; IMS and XRST handle repositioning automatically.
JCL for IMS Batch: - DFSRRC00 is the IMS region controller invoked by JCL. - The PARM field specifies region type, program name, PSB name, and processing options. - DD statements include STEPLIB, DFSRESLB, IMS (DBDLIB/PSBLIB), IEFRDER (log), DFSVSAMP (buffers), and database datasets.
IMS-COBOL Integration Patterns: - Sequential batch processing: XRST, GN loop, periodic CHKP, final CHKP. - Online inquiry: GU IO-PCB, GU DB-PCB, GNP loop, ISRT IO-PCB. - Online update: GU IO-PCB, GHU DB-PCB, modify, REPL, ISRT IO-PCB. - Cross-database operations use separate PCBs with independent positions.
In the next chapter, we will explore additional enterprise data access technologies that complement the IMS, DB2, and CICS skills you have built throughout Part V of this book.