Using client/server processing

CICS® business transaction services support client/server processing. A server process is one that is typically waiting for work. When work arrives, BTS restarts the process, which retrieves any state data that it has previously saved.

Typically, the client invokes the server with a named input event, and sends it some input data in a data-container. From these inputs, the server determines what actions it needs to take. It returns any output for the client in a data-container.

When the client has dealt with any output returned by the server, it releases the server process. Releasing the server means that its in-memory instance is freed. At this point, the server process is maintained only by BTS.

A client/server example

The client/server example in this section shows:

  1. A client program initiating a server process and calling it with some work to do.
  2. The server defining some input events for which it may be reinvoked; then performing some work and returning output to the client.
  3. After dealing with the output returned by the server, the client releasing the in-memory instance of the server.
  4. The client reacquiring the server process and requesting it to run again.
  5. The server process determining the input event that caused it to be reinvoked, and retrieving some state data that it saved when it last ran; then performing some work and returning output to the client.
  6. Eventually, the client telling the server to shut down, and the server responding to this event by indicating that it should not be reinvoked.

The client program

Figure 19 shows, in COBOL pseudocode, the example client program, PRG001.

Figure 19. Example client program, PRG001
Identification Division.
Program-id. PRG001.
Environment Division.
Data Division.
Working-Storage Section.
01  RC                            pic s9(8) comp.
01  Unique-Reference              pic x(36) value low-values.
    .
01  Process-Type                  pic x(8)  value 'Servers'.
    .
01  Event-Name                    pic x(16) value low-values.
    .
01  Work-Buffer.
    .
01  Work-request                  Pic x.
    88  Work-New                  value 'N'.
    88  Work-Continue             value 'C'.
    88  Work-End                  value 'E'.
 
Linkage Section.
01  DFHEIBLK.
    .
01  DFHCOMMAREA.
    .
    .
Procedure Division using DFHEIBLK DFHCOMMAREA.
In-The-Beginning.
    .
    EXEC CICS SEND ...
         RESP(data-area) END-EXEC
    .
    EXEC CICS RECEIVE ...
         RESP(data-area) END-EXEC
    .
    Move ..unique.. TO Unique-Reference
    Move ..request.. TO Work-Request
    .
    Evaluate True
      When Work-New
        Perform New-Process
      When Work-Continue
        Move 'SRV-WORK' TO Event-Name
        Perform Existing-Process
      When Work-End
        Move 'SRV-SHUTDOWN' TO Event-Name
        Perform Existing-Process
      When Other
        .
    End Evaluate.
 
    .
    EXEC CICS GET CONTAINER('Server-Out')
                 ACQPROCESS INTO(Work-Buffer)
             RESP(data-area) RESP2(data-area) END-EXEC
    .
    EXEC CICS SEND ...
         RESP(data-area) END-EXEC
    .
    EXEC CICS RETURN END-EXEC
    .
New-Process.
    .
    EXEC CICS DEFINE PROCESS(Unique-Reference) PROCESSTYPE(Process-Type)
                 TRANSID('SERV')
                 PROGRAM('SRV001')
             RESP(data-area) RESP2(data-area) END-EXEC
    .
    EXEC CICS PUT CONTAINER('Server-In')
                 ACQPROCESS FROM(Work-Buffer)
             RESP(data-area) RESP2(data-area) END-EXEC
    .
    EXEC CICS RUN ACQPROCESS
                 SYNCHRONOUS
             RESP(RC) RESP2(data-area) END-EXEC
    .
Existing-Process.
    .
    EXEC CICS ACQUIRE PROCESS(Unique-Reference) PROCESSTYPE(Process-Type)
             RESP(data-area) RESP2(data-area) END-EXEC
    .
    EXEC CICS PUT CONTAINER('Server-In')
                 ACQPROCESS FROM(Work-Buffer)
             RESP(data-area) RESP2(data-area) END-EXEC
    .
    EXEC CICS RUN ACQPROCESS
                 SYNCHRONOUS
                 INPUTEVENT(Event-Name)
             RESP(RC) RESP2(data-area) END-EXEC
    .
End Program.

First, PRG001 determines if this is the first time the server is to be called. If it is, it establishes a unique name for this instance of the server process. Then it creates the server process by issuing an DEFINE PROCESS command with that unique name. PRG001 provides some input data for the server in a data-container named Server-In:

    EXEC CICS PUT CONTAINER('Server-In')
                 ACQPROCESS FROM(Work-Buffer)
             RESP(data-area) RESP2(data-area) END-EXEC

The ACQPROCESS option associates the Server-In container with the process that PRG001 has "acquired". A program "acquires" access to a process in one of two ways: either, as here, by defining it; or, if the process has already been defined, by issuing an ACQUIRE PROCESS command.

Having created the server process, PRG001 issues a request to run it synchronously. The RUN ACQPROCESS command causes the currently-acquired process to be activated. Because RUN ACQPROCESS rather than LINK ACQPROCESS is used, the server process is run in a separate unit of work from that of the client. PRG001 waits for the server to run, and then retrieves any data returned from a data-container named Server-Out.

PRG001 has now temporarily finished using the server process; the implicit syncpoint at RETURN causes it to be released.

To use this instance of the server again, PRG001 must first acquire access to the correct process. It does this by issuing an ACQUIRE PROCESS command which specifies the unique combination of the process’s name and process-type:

    EXEC CICS ACQUIRE PROCESS(Unique-Reference) PROCESSTYPE(Process-Type)
             RESP(data-area) RESP2(data-area) END-EXEC

Once again, PRG001 provides input data for the server in a data-container named Server-In, and requests the process to be run:

    EXEC CICS RUN ACQPROCESS
                 SYNCHRONOUS
                 INPUTEVENT(Event-Name)
             RESP(RC) RESP2(data-area) END-EXEC

PRG001 uses the INPUTEVENT option of the RUN command to tell the server why it has been invoked--in this case, it is for SRV-WORK. (The server must have defined an input event of that name.)

Again, PRG001 waits for the process to complete, retrieves any returned data, and releases the process.

Eventually, PRG001 tells the server to shut down by invoking it with an event of SRV-SHUTDOWN.

The server program

Figure 20 shows, in COBOL pseudocode, the example server program, SRV001.

Figure 20. Example server program, SRV001
Identification Division.
Program-id. SRV001.
Environment Division.
Data Division.
Working-Storage Section.
01  Event-Name                   pic x(16).
    88  DFH-Initial              value 'DFHINITIAL'.
    88  SRV-Request              value 'SRV-REQUEST'.
01  Sub-Event-Name               pic x(16).
    88  SRV-Work                 value 'SRV-WORK'.
    88  SRV-Shutdown             value 'SRV-SHUTDOWN'.
01  Input-Buffer.
    .
01  Output-Buffer.
    .
01  State-Buffer.
    .
Linkage Section.
01  DFHEIBLK.
    .
Procedure Division.
Begin-Process.
      .
    EXEC CICS RETRIEVE REATTACH EVENT(Event-Name)
             RESP(data-area) RESP2(data-area) END-EXEC
      .
    Evaluate True
      When DFH-Initial
        Perform Initial-Request
        Perform Server-work
      When SRV-Request
        Perform Server-Event
      When Other
         .
    End Evaluate.
        .
    EXEC CICS RETURN END-EXEC
    .
Server-Event.
      .
    EXEC CICS RETRIEVE SUBEVENT(Sub-Event-Name) EVENT(Event-Name)
             RESP(data-area) RESP2(data-area) END-EXEC
    .
    Evaluate True
      When SRV-Work
        Perform Server-Work
      When SRV-Shutdown
        Perform Server-Shutdown
      When Other
         .
    End Evaluate.
    .
Initial-Request.
    .
    EXEC CICS DEFINE INPUT EVENT('SRV-WORK')
             RESP(data-area) RESP2(data-area) END-EXEC
    .
    EXEC CICS DEFINE INPUT EVENT('SRV-SHUTDOWN')
             RESP(data-area) RESP2(data-area) END-EXEC
    .
    EXEC CICS DEFINE COMPOSITE EVENT('SRV-REQUEST') OR
                 SUBEVENT1('SRV-WORK')
                 SUBEVENT2('SRV-SHUTDOWN')
             RESP(data-area) RESP2(data-area) END-EXEC
    .
    Server-Work.
    .
    EXEC CICS GET CONTAINER('Server-In') INTO(Input-Buffer)
             RESP(data-area) RESP2(data-area) END-EXEC
    .
    If DFH-Initial
       EXEC CICS DEFINE ACTIVITY('Work')
                    TRANSID('SWRK')
                    PROGRAM('PRG002')
                RESP(data-area) RESP2(data-area) END-EXEC
       .
    Else
       EXEC CICS GET CONTAINER('Previous-State') INTO(State-Buffer)
                RESP(data-area) RESP2(data-area) END-EXEC
       .
    End-If.
    .
    EXEC CICS PUT CONTAINER('Work-Input')
                 ACTIVITY('Work') FROM(Input-Buffer)
             RESP(data-area) RESP2(data-area) END-EXEC
    .
    EXEC CICS RUN ACTIVITY('Work')
                 SYNCHRONOUS
             RESP(data-area) RESP2(data-area) END-EXEC
    EXEC CICS CHECK ACTIVITY('Work') COMPSTATUS(status)
             RESP(RC) RESP2(data-area) END-EXEC
    .
    If RC NOT = DFHRESP(NORMAL)
        .
    End-If.
    .
    If status NOT = DFHVALUE(NORMAL)
        .
    End-If.
    .
    EXEC CICS GET CONTAINER('Work-Output')
                 ACTIVITY('Work') INTO(Output-Buffer)
             RESP(data-area) RESP2(data-area) END-EXEC
    .
    EXEC CICS PUT CONTAINER('Previous-State') FROM(State-Buffer)
             RESP(data-area) RESP2(data-area) END-EXEC
    .
    EXEC CICS PUT CONTAINER('Server-Output') FROM(Output-Buffer)
             RESP(data-area) RESP2(data-area) END-EXEC
    .
Server-Shutdown.
    EXEC CICS DELETE EVENT('SRV-WORK')
             RESP(data-area) RESP2(data-area) END-EXEC
    .
    EXEC CICS DELETE EVENT('SRV-SHUTDOWN')
             RESP(data-area) RESP2(data-area) END-EXEC
    .
    EXEC CICS DELETE EVENT('SRV-REQUEST')
             RESP(data-area) RESP2(data-area) END-EXEC
    .
    EXEC CICS RETURN ENDACTIVITY
             RESP(data-area) RESP2(data-area) END-EXEC
End Program.

The server program, SRV001, first issues a RETRIEVE REATTACH EVENT command to determine the reason for its invocation. On its first invocation, the event returned is DFHINITIAL, which tells SRV001 to perform any initial housekeeping. SRV001’s housekeeping includes defining two input events for which it could subsequently be reinvoked:

    EXEC CICS DEFINE INPUT EVENT('SRV-WORK')
             RESP(data-area) RESP2(data-area) END-EXEC
    .
    EXEC CICS DEFINE INPUT EVENT('SRV-SHUTDOWN')
             RESP(data-area) RESP2(data-area) END-EXEC
    .
    EXEC CICS DEFINE COMPOSITE EVENT('SRV-REQUEST') OR
                  SUBEVENT1('SRV-WORK')
                  SUBEVENT2('SRV-SHUTDOWN')
             RESP(data-area) RESP2(data-area) END-EXEC
    .
 

The DEFINE COMPOSITE EVENT command defines a third, composite, event (SRV-REQUEST), and adds the two input events to it. Because the composite event uses the OR Boolean operator, it will fire when either of the two input events fires; SRV001 will be reattached.

SRV001 obtains its input data from a data-container named Server-In. It then performs the work activity Work.

When the work activity has completed, SRV001 saves some state data for the next time it is run, and returns the output data produced by the work activity to the client program in a data-container named Server-Output.

On subsequent invocations, SRV001 determines that it has been invoked to perform work. (The RETRIEVE REATTACH EVENT command returns the composite event SRV-REQUEST, and a RETRIEVE SUBEVENT command with an event-name of SRV-REQUEST returns the sub-event SRV-WORK.)

Eventually, the RETRIEVE SUBEVENT command returns the sub-event SRV-SHUTDOWN, and SRV001 responds by ending the server process. First it deletes the user events that it has defined, then issues an EXEC CICS RETURN ENDACTIVITY command to indicate that it has completed all its processing.

Related concepts
Introduction
Using the BTS API to write business applications
The Sale example application
Related tasks
Acquiring an activity
Transferring data to asynchronous activations
Related reference
Overview of BTS API commands
BTS application programming commands
[[ Contents Previous Page | Next Page Index ]]