PSB scheduling for CICS environments

PSB scheduling is handled differently in the CICS® environment 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.

PSB scheduling

Before a CICS DL/I program can access the databases defined in a PSB, the program must schedule the PSB. The program must end the PSB when database access is complete. Rational® COBOL Runtime 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 ends.
Database positioning
Database position is lost when the PSB ends.
Update commitment
Changes are committed (written to the database) when the PSB ends.

The PSB is scheduled whenever a DL/I call is issued for the program and the PSB is not currently scheduled. The PSB that is named in dliLib.psbData.psbName is the PSB scheduled.

When you use a call or transfer to program statement to transfer program control, the target program does not have to use the same PSB that 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 by using a transfer to program 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 statement, and either of the following is set to 1:
    • converseVar.segmentedMode (defaults to 1 if the program property is set to YES)
    • converseVar.commitOnConverse
  • A transfer that uses a transfer to transaction statement occurs
  • A program invokes the sysLib.commit function.
  • When a PSB is currently scheduled, an EGL program transfers by using a transfer to program statement and one of the following occurs:
    • The transfer is to a non-EGL (and non-VisualAge Generator) program.
    • The synchOnPgmTransfer build descriptor option is set to YES for the transferring program.
    • The synchOnPgmTransfer build descriptor option is set to NO for the transferring program and the default PSB that is referenced in the PSB record of the transferring program is different from the default PSB referenced in the PSB record of the target program. To minimize the difference in behavior when a transferring program generates for both CICS and IMS/VS, set the synchOnPgmTransfer build descriptor option to NO.
  • 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 invokes the sysLib.rollback function.
  • 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.

Alternate PSBs at run time

When you create a DL/I program, use the psb property to specify the name of a program variable that is based on a PSBRecord part. EGL uses the PSBRecord that is associated with this variable to create DL/I calls for the segments that are defined in the PSB and to validate the changes you make to the DL/I calls. In the CICS environment, Rational COBOL Runtime also uses the PSB name for PSB scheduling at the time the program is run.

However, you might want to use an alternate PSB with the same program. The alternate PSB describes databases that have the same structure as the program PSB, although 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, your program can dynamically change the scheduled PSB 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 for the database names.

Share 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 ends the PSB prior to each call or return to a program that uses a different PSB. When your program sets the callInterface property to CBLTDLI, you can share the PSB with another program by passing the dliLib.psbData structure or the PCB records on the call for both the called and the calling program. When your program sets the callInterface property to AIBTDLI (the default), pass the dliLib.psbData structure or the PCB records if the calling or called program is a non-EGL program.

If the called and calling programs are both EGL programs and 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 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 you share 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. 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.

Recover after a deadlock in record queuing

Updated records are not written to the database until the PSB ends. 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 until it is written to the database. This can result in the following deadlock situation:
  • Your program (Program1) locks RecordA.
  • Another program (Program2) locks RecordB.
  • You attempt to change RecordB.
  • Program2 attempts to change RecordA at the same time.

When CICS detects a deadlock situation, it abnormally ends one of the programs, backs out the changes it 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" in this topic.

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

If your program is running in segmented (CICS 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 nonsegmented (CICS conversational) program is restarted, the program begins again at the top of the program. 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.

Restart EGL-generated programs after a DL/I deadlock

When the DL/I program isolation facility is used, deadlocks can occur between two transactions that lock 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 detects that data is lost, it abnormally ends the transaction with an ADLD abend code.

The Rational COBOL Runtime abend handler requests restart for programs that end with a deadlock abend. CICS restarts the transaction from the beginning in the following situations:
  • You have specified DTB=YES and RESTART=YES in the PCT for the transaction program.
  • The CICS transaction restart program (DFHRTY) specifies to restart the transaction.
  • The temporary storage queues are defined as recoverable.

Otherwise, CICS writes a message that indicates 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 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 verify that it meets the following conditions:
  • 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 that restart is to continue. For more information on modifying DFHRTY, see the recovery, restart, and customization manuals for your CICS system.

If restart is requested, programs running in segmented mode (CICS pseudoconversational) must have all the CICS resources that are to be updated defined as recoverable. The names of the temporary storage queues that are created by the segmentation function of Rational COBOL Runtime consist of the terminal identifier for the user 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 nonsegmented (CICS conversational) programs unless you have designed the program to handle restart. One simple way is to have the program test dliVar. cicsRestart whenever it begins. If the restart flag is on, a special message or form should appear to User 1 with the following information:
  • The transaction was restarted at the beginning because User 2 was changing the database at the same time.
  • The changes that User 1 made were backed out.
  • The program was restarted to prevent changes from being lost.

Access to distributed DL/I databases

Programs that run on CICS can access DL/I databases on remote systems by calling a basic program that runs on the system where the database is located.


Feedback