DL/I considerations for CICS environments

In the CICS® environment, PSB scheduling is handled differently than in non-CICS environments. The following sections describe PSB scheduling, how to use an alternate PSB at run time and how to share a PSB with a called program.

Understanding PSB scheduling

A CICS DL/I program must schedule a PSB before the program can access databases defined in that PSB. The program must end the PSB when database access is complete. Enterprise Developer Server for z/OS® automatically handles PSB scheduling for a program. However, you need to know when the PSB is scheduled because the following functions are affected by PSB scheduling:
Segment record locking
Segment update locks are released when the PSB is ended.
Database positioning
Database position is lost when the PSB is ended.
Update commitment
Changes are committed (written to the database) when the PSB is ended.
The PSB is scheduled whenever a DL/I call is issued for the program and the PSB is not currently scheduled. The PSB named in dliLib.psbData.psbName is the PSB scheduled.

When using a CALL or DXFR statement to transfer program control, the transferred-to program does not have to use the same PSB the transferring program uses.

The PSB ends whenever a CICS SYNCPOINT or SYNCPOINT ROLLBACK is issued. SYNCPOINTs occur when one of the following occurs:
  • The top-level program in a run unit ends successfully and returns control to CICS. For CICS, a run unit is equivalent to a single transaction and consists of all EGL programs and non-EGL programs that transfer control among themselves using a DXFR or CALL statement. For non-EGL programs, this also includes any transfer that uses a CALL statement, CICS LINK command, or CICS XCTL command.
  • A program uses a CONVERSE I/O option, and either of the following is set to 1:
    • converseVar.segmentedMode (defaults to 1 if the program is defined as segmented)
    • converseVar.commitOnConverse
  • A transfer using an XFER statement occurs
  • A program calls either the sysLib.commit() function or the COMMIT service.
  • A transfer using a DXFR statement occurs, a PSB is scheduled, and one of the following occurred:
    • Transfer to a non-EGL program when a PSB is scheduled.
    • The synchOnPgmTransfer generation option was set to yes for the transferred-from program
    • The synchOnPgmTransfer generation option was set to no for the transferred-from program and different PSB names were identified in the program specifications for the two programs.
  • An EGL-called DL/I program returns to the calling non-EGL program, the PSB was not passed in the DLILib.psbData structure, and PCBs were not passed using PCB records.
A SYNCPOINT ROLLBACK occurs when:
  • An EGL program calls the sysLib.rollback() function or the RESET service.
  • A program ends because of an error condition.
When a rollback occurs, all changes that were made to databases and recoverable files since the start of the logical unit of work (LUW) are backed out.

Using an alternate PSB at run time

EGL uses the PSB named in the program specification to create DL/I calls for the segments defined in the PSB and to validate any changes you make to the DL/I calls. In the CICS environment, Enterprise Developer Server for z/OS also uses the PSB name for PSB scheduling at the time the program is run.

Sometimes, however, you might want to use an alternate PSB with the same program. The alternate PSB describes databases with the exact same structure as the program PSB, but the databases themselves might be different. For example, you could have a set of test databases for program development and a corresponding set of production databases that contain the real data for production.

If you want to use an alternate PSB for any reason, your program can dynamically change the PSB that is scheduled by moving the alternate PSB name into DLIVar.dliPsbName before running the first DL/I function. The alternate PSB must match the program PSB except that the database names can be different.

Sharing a scheduled PSB with a called program

Called and calling programs cannot both be DL/I programs unless they share the same program PSB or unless a commit is done to end the PSB prior to each call or return to a program that uses a different PSB. The PSB is shared by passing the DLILib.psbData structure or the PCB records on the call for both the called and the calling program.

If the called and calling programs are both EGL programs, and if the PSB was scheduled before the call, EGL does not reschedule the PSB in the called program.

You can share a PSB between EGL programs and non-EGL programs. When the DLILib.psbData structure is passed as a parameter, a 12-byte area is actually passed. The first 8 bytes contain the PSB name; the final 4 bytes contain the address of the CICS User Interface Block (UIB). If the PSB is not scheduled, the UIB address is 0. When sharing a PSB between EGL programs and non-EGL programs, the called program should check the UIB address before scheduling. If the UIB address is not 0, the PSB should not be rescheduled. If the called program ends the PSB, it must set the UIB address field to 0. If the PSB is scheduled again, the UIB address field should be set to the UIB address returned by CICS.

If a program needs to share a scheduled PSB with a called EGL program, it should pass a 12-byte area to the program. Again, the first 8 bytes should contain the PSB name and the next 4 bytes should contain the UIB address. If the PSB is not scheduled, the UIB address should be 0. On return, the UIB address reflects the current scheduling status of the PSB.

Recovering after a deadlock in record queuing

Updated records are not actually written to the database until the PSB is ended. Your program obtains exclusive use of these records until PSB termination because the EGL get...forUpdate I/O statement locks out other programs from changing the record again until it is actually written to the database. This can result in a deadlock situation where your program has some record locked and now wants to change records locked by another program that in turn needs the records you have locked. When CICS detects a deadlock situation, it abnormally ends one of the programs, backs out the changes it has made to the database, and writes an error message to the terminal explaining why the program ended.

If having a program abnormally end is unacceptable to the users of the program, you can define your program as restartable in the CICS tables. For information on restarting programs, see "Restarting EGL programs after a DL/I deadlock" later in this topic.

If the program is restartable and CICS detects a deadlock situation, CICS backs out the changes that the program has made since the PSB was scheduled and restarts the program from the beginning of the transaction.

If your program is running in segmented (pseudoconversational) mode, the most recent segment of the program is restarted, and you do not need any special restart code in the program.

If a conversational program is restarted, the program begins again at the top. You can determine that the program was restarted by having the program test for a value of 1 in the DLIVar.cicsRestart field. If DLIVar.cicsRestart is 1, you can write a message to the program user explaining that the program was restarted because of a deadlock and then display the initial program map again.

Restarting VisualAge® Generator programs after a DL/I deadlock

When the DL/I program isolation facility is used, deadlocks can occur between two transactions locking on the same record. The programs try to update the same record at the same time. If both updates are accepted, one of the changes is lost. If CICS for MVS/ESA™ or CICS for VSE/ESA™ detects that data is lost, it abnormally ends the transaction with an ADLD abend code.

The Enterprise Developer Server for z/OS abend handler requests restart for programs that end with a deadlock abend. CICS for MVS/ESA or CICS for VSE/ESA restarts the transaction from the beginning if:
  • You have specified DTB=YES and RESTART=YES in the PCT for the transaction program.
  • The CICS for MVS/ESA or CICS for VSE/ESA transaction restart program (DFHRTY) specifies to restart the transaction.
  • The temporary storage queues are defined as recoverable.
Otherwise, CICS for MVS/ESA or CICS for VSE/ESA writes a message indicating the reason for program termination. A restarted program is a program that is started again from the beginning of the last transaction that was running. All changes to databases that were made since the program PSB was last scheduled are rolled back.
The distributed version of the CICS for MVS/ESA or CICS for VSE/ESA restart program (DFHRTY) does not restart an EGL-generated program from the beginning of the last database transaction that was running. You can add code to DFHRTY to restart EGL database transactions. Your program should check that the following is true:
  • The current abend code is ADLD.
  • The transaction identifier is the identifier of the transaction you want restarted.
  • The restart count is less than the specified number. This is a restart loop check.
If all checks are met, your program should set the restart flag to on, indicating to CICS for MVS/ESA or CICS for VSE/ESA that restart is to continue. For more information on modifying DFHRTY, refer to the recovery, restart, and customization manuals for your CICS for MVS/ESA or CICS for VSE/ESA system.

Programs running in segmented mode must have all the CICS for MVS/ESA or CICS for VSE/ESA resources (that are to be updated) defined as recoverable if restart is requested. The names of the temporary storage queues that are created by the segmentation function of Enterprise Developer Server for z/OS are a combination of the user's terminal identifier appended to a 4-character prefix. The prefixes used are in the form of X‘EE‘ followed by either WRK or MSG.

You should not request restart for conversational programs unless you have designed the program to handle restart. A program can test the DLIVar.cicsRestart field to see if the current program transaction has been restarted. One simple way of designing a program for restart is to have the program test cicsRestart whenever it begins. If the restart flag is on, a special message or map should appear to user 1 explaining that the transaction was restarted at the beginning because user 2 was changing the database at the same time. User 1's changes were backed out, and the program was restarted to prevent the changes from being lost.

Accessing distributed DL/I databases

Programs running on CICS for MVS/ESA, CICS for VSE/ESA, or CICS for OS/2® systems can access DL/I databases on remote systems by calling a CICS for MVS/ESA- or CICS for VSE/ESA-called batch server program that runs on the system where the database is located.

Feedback
(C) Copyright IBM Corporation 2000, 2005. All Rights Reserved.