Unsafe programming for affinity

Some CICS® application programming techniques, notably those that pass, or obtain, addresses to shared storage, create an affinity between transactions.

The programming techniques that are generally unsafe are described in the following sections.

Using the common work area

The CWA in a CICS region is created (optionally) during CICS initialization, exists until CICS terminates, and is not recovered on a CICS restart (warm or emergency). The ADDRESS CWA(ptr-ref) command provides direct addressability to the CWA.

A good example of how the use of long-life shared storage such as the CWA can create affinity is when one task stores data in the CWA, and a later task reads the data from it. Clearly, the task retrieving the data must run in the same target region as the task that stored the data, or it references a completely different storage area in a different address space. This restricts the workload balancing capability of the dynamic or distributed routing program, as shown in Figure 56.

Figure 56. Illustration of inter-transaction affinity created by use of the CWA. The dynamic routing program needs to be aware of this CWA affinity, and ensure it routes TRN2 to the same target region as TRN1.
 TRN1 executing in region AOR1 writes data to the CWA intended for TRN2. The TOR routes TRN2 to AOR3, where it cannot access the CWA belonging to AOR1.
CWA

However, if the CWA contains read-only data, and this data is replicated in more than one target region, it is possible to use the CWA and continue to have the full benefits of dynamic routing. For example, you can run a program during the post-initialization phase of CICS startup (a PLTPI program) that loads the CWA with read-only data in each of a number of selected target regions. In this way, all transactions routed to target regions loaded with the same CWA data have equal access to the data, regardless of which of the target regions to which the transactions are routed. With CICS subsystem storage protection, you can ensure the read-only integrity of the CWA data by requesting the CWA from CICS-key storage, and define all the programs that read the CWA to execute in user key.

Using GETMAIN SHARED storage

Shared storage is allocated by a GETMAIN SHARED command, and remains allocated until explicitly freed by the same, or by a different, task. Shared storage can be used to exchange data between any CICS tasks that run during the lifetime of the shared storage. Transactions designed in this way must execute in the same CICS region to work correctly. The dynamic or distributed routing program should ensure that transactions using shared storage are routed to the same target region.

Figure 57 illustrates the use of shared storage.

Figure 57. Illustration of inter-transaction affinity created by use of shared storage. The dynamic transaction routing program needs to be aware of this affinity, and ensure it routes TRN2 to the same target region as TRN1.
 TRN1 executes in AOR1, GETMAINS shared storage, writes data to it and stores the address in a TS queue. TRN2 reads the address from the TS queue, reads the data and FREEMAINs the storage.

If the two transactions shown in Figure 57 are parts of a pseudoconversational transaction, the use of shared storage should be replaced by a COMMAREA (provided that the amount of storage fits within the COMMAREA size limits).

Using the LOAD PROGRAM HOLD command

A program (or table) that CICS loads in response to a LOAD PROGRAM HOLD command remains in directly addressable storage until explicitly released by the same, or by a different, task. Any CICS tasks that run while the loaded program (table) is held in storage can use the loaded program’s storage to exchange data, provided that:

Although you could use a temporary storage queue to make the address of the loaded program’s storage available to other tasks, the more usual method would be for other tasks to issue a LOAD PROGRAM command also, with the SET(ptr_ref) option so that CICS can return the address of the held program.

The nature of the affinity caused by the use of the LOAD PROGRAM HOLD command is virtually identical to that caused by the use of GETMAIN SHARED storage (see Figure 57 and Figure 58), and the same rule applies: to preserve the application design, the dynamic or distributed routing program must ensure that all transactions that use the address of the loaded program (or table) are routed to the same target region.

Figure 58. Illustration of inter-transaction affinity created by use of LOAD PROGRAM HOLD. The dynamic routing program needs to be aware of this affinity, and ensure it routes TRN2 to the same target region as TRN1.
 TRN1 executes in AOR1 and issues LOAD PROGRAM HOLD. Other programs that issue LOAD PROGRAM with SET also execute in the same AOR.
Note:
This rule applies also to programs defined with the RESIDENT option on the resource definition for the loaded program (whether or not the HOLD option is specified on the LOAD command). However, regardless of affinity considerations, it is unsafe to use the RESIDENT option to enable transactions to share data, because programs defined with RESIDENT are subject to SET PROGRAM(program_name) NEWCOPY commands, and can therefore be changed.

The rule also applies to a non-resident, non-held, loaded program where the communicating tasks are synchronized.

Sharing task-lifetime storage

The use of any task-lifetime storage belonging to one task can be shared with another task, provided the owning task can pass the address to the other task in the same CICS address space. This technique creates an affinity among the communicating tasks, and requires that any task retrieving and using the passed address must execute in the same target region as the task owning the task-lifetime storage.

For example, it is possible to use a temporary storage queue to pass the address of a PL/I automatic variable, or the address of a COBOL working-storage structure (see Figure 59 for an example).

Figure 59. Illustration of inter-transaction affinity created by use of task-lifetime storage. TRN2 must execute in the same target region as TRN1. Also, TRN1 must not terminate until TRN2 has finished using its task-lifetime storage.
 TRN1 executes in AOR1 and stores the address of task-lifetime storage in a TS queue for TRN2 and suspends. TRN2 executes in AOR1, accesses the storage and resumes TRN1.

For two tasks to share task-lifetime storage belonging to one of them requires that the tasks are synchronized in some way. See Table 17 for commands that provide ways of suspending and resuming a task that passes the address of its local storage.

Table 17. Methods for suspending and resuming (synchronizing) tasks
Suspending operation Resuming operation
WAIT EVENT, WAIT EXTERNAL, WAITCICS POST
RETRIEVE WAIT START
DELAY CANCEL
POST CANCEL
START CANCEL
ENQ DEQ

Some of these techniques themselves require that the transactions using them must execute in the same target region, and these are discussed later in this chapter. However, even in those cases where tasks running in different target regions can be synchronized, it is not safe to pass the address of task-lifetime storage from one to the other. Even without dynamic routing, designs that are based on the synchronization techniques shown in Table 17 are fundamentally unsafe because it is possible that the storage-owning task could be purged.

Notes:
  1. Using synchronization techniques, such as RETRIEVE WAIT/START, to allow sharing of task-lifetime storage is unsafe in CICS Version 2 because the task issuing, for example, the RETRIEVE WAIT could be purged by a CEMT SET TASK(...) PURGE command. In CICS/ESA Version 3 and later, the SPURGE parameter on the transaction definition could be used to protect the first task, but even so the design is not recommended.
  2. No inter-transaction affinity is caused in those cases where the task sharing another task’s task-lifetime storage is started by an START command, except when the START command is function-shipped or routed to a remote system.

Using the WAIT EVENT command

The WAIT EVENT command is used to synchronize a task with the completion of an event performed by some other CICS or MVS™ task.

The completion of the event is signalled (posted) by the setting of a bit pattern into the event control block (ECB). Both the waiting task and the posting task must have direct addressability to the ECB, hence both tasks must execute in the same target region. The use of a temporary storage queue is one way that the waiting task can pass the address of the ECB to another task.

This synchronization technique is illustrated in Figure 60.

Figure 60. Illustration of inter-transaction affinity created by use of WAIT EXTERNAL command. TRN2 must execute in the same target region as TRN1.
 TRN1 executes in AOR1. It stores the address of an ECB in a TS queue for TRN2, then suspends with WAIT EVENT ECADDR (ptr-ref). TRN2 executes in AOR1 then reads the address of the ECB, posts it and returns. TRN1 is then resumed.

If TRN2 shown in Figure 60 executed in a different target region from TRN1, the value of ptr-ref would be invalid, the post operation would have unpredictable results, and the waiting task would never be resumed. For this reason, a dynamic or distributed routing program must ensure that a posting task executes in the same target region as the waiting task to preserve the application design. The same considerations apply to the use of WAIT EXTERNAL and WAITCICS commands for synchronizing tasks.

Using ENQ and DEQ commands without ENQMODEL resource definitions

The ENQ and DEQ commands are used to serialize access to a shared resource. These commands only work for CICS tasks running in the same region, and cannot be used to serialize access to a resource shared by tasks in different regions, unless they are supported by appropriate ENQMODEL resource definitions so that they have sysplex-wide scope.See Using ENQ and DEQ commands with ENQMODEL resource definitions and the CICS Resource Definition Guide for a description of ENQMODELs.

Note that any ENQ that does not specify the LENGTH option is treated as an enqueue on an address and therefore has only local scope.The use of ENQ and DEQ for serialization (without ENQMODEL definitions to give sysplex-wide scope) is illustrated in Figure 61.

Figure 61. Illustration of inter-transaction affinity created by use of ENQ/DEQ commands. TRN2 must execute in the same target region as TRN1.
 TRN1 executes in AOR!. It issues an ENQ command on the resource name of a shared resource and uses the resource. TRN2 executes in AOR1 and issues an ENQ on the same resource. It is suspended by CICS until TRN1 issues a DEQ.

If TRN2 shown in Figure 61 executed in a different target region from TRN1, TRN2 would not be suspended while TRN1 accessed the shared resource. For this reason, a dynamic or distributed routing program must ensure that all tasks that enqueue on a given resource name must execute in the same target region to preserve the application design. TRN2 would, of course, be serialized with other CICS tasks that issue ENQ commands on the same resource name in its target region.

[[ Contents Previous Page | Next Page Index ]]