The IccStartRequestQ class enables a program to start another CICS® transaction instance asynchronously (and optionally pass data to the started transaction). The same class is used by a started transaction to gain access to the data that the task that issued the start request passed to it. Finally start requests (for some time in the future) can be cancelled.
You can use any of the following methods to establish what data will be sent to the started transaction:
The actual start is requested using the start method.
A started transaction can access its start data by invoking the retrieveData method. This method stores all the start data attributes in the IccStartRequestQ object such that the individual attributes can be accessed using the following methods:
Unexpired start requests (that is, start requests for some future time that has not yet been reached) can be cancelled using the cancel method.
CICS system | ICC1 | ICC2 |
---|---|---|
Transaction | ISR1/ITMP | ISR2 |
Program | ICC$SRQ1/ICC$TMP | ICC$SRQ2 |
Terminal | PEO1 | PEO2 |
The scenario is as follows. We start transaction ISR1 on terminal PEO1 on system ICC1. This issues two start requests; the first is cancelled before it has expired. The second starts transaction ISR2 on terminal PEO2 on system ICC2. This transaction accesses its start data and finishes by starting transaction ITMP on the original terminal (PEO1 on system ICC1).
The programs can be found in the samples directory (see Sample source code) as files ICC$SRQ1 and ICC$SRQ2. Here the code is presented without the terminal IO requests.
Transaction ISR1 runs program ICC$SRQ1 on system ICC1. Let us consider this program first:
#include "icceh.hpp"
#include "iccmain.hpp"
void IccUserControl::run()
{
These lines include the header files for the Foundation Classes, and the main function needed to set up the class library for the application program. The run method of IccUserControl class contains the user code for this example.
IccRequestId req1;
IccRequestId req2("REQUEST1");
IccTimeInterval ti(0,0,5);
IccTermId remoteTermId("PE02");
IccTransId ISR2("ISR2");
IccTransId ITMP("ITMP");
IccBuf buffer;
IccStartRequestQ* startQ = startRequestQ();
Here we are creating a number of objects:
Finally, the startRequestQ method of IccControl class returns a pointer to the single instance (singleton) class IccStartRequestQ.
startQ->setRouteOption( "ICC2" );
startQ->registerData( &buffer );
startQ->setReturnTermId( terminal()->name() );
startQ->setReturnTransId( ITMP );
startQ->setQueueName( "startqnm" );
This code fragment prepares the start data that is passed when we issue a start request. The setRouteOption says we will issue the start request on the remote system, ICC2. The registerData method associates an IccBuf object that will contain the start data (the contents of the IccBuf object are not extracted until we actually issue the start request). The setReturnTermId and setReturnTransId methods allow the start requester to pass a transaction and terminal name to the started transaction. These fields are typically used to allow the started transaction to start another transaction (as specified) on another terminal, in this case ours.
The setQueueName is another piece of information that can be passed to the started transaction.
buffer = "This is a greeting from program 'icc$srq1'!!";
req1 = startQ->start( ISR2, &remoteTermId, &ti );
startQ->cancel( req1 );
Here we set the data that we pass on the start requests. We start transaction ISR2 after an interval ti (5 seconds). The request identifier is stored in req1. Before the five seconds has expired (that is, immediately) we cancel the start request.
req1 = startQ->start( ISR2, &remoteTermID, &ti, &req2 );
return;
}
Again we start transaction ISR2 after an interval ti (5 seconds). This time the request is allowed to expire so transaction ISR2 is started on the remote system. Meanwhile, we end by returning control to CICS.
Let us now consider the started program, ICC$SRQ2.
IccBuf buffer;
IccRequestId req("REQUESTX");
IccTimeInterval ti(0,0,5);
IccStartRequestQ* startQ = startRequestQ();
Here, as in ICC$SRQ1, we create a number of objects:
The startRequestQ method of IccControl class returns a pointer to the singleton class IccStartRequestQ.
if ( task()->startType() != IccTask::startRequest )
{
term->sendLine(
"This program should only be started via the StartRequestQ");
task()->abend( "OOPS" );
}
Here we use the startType method of IccTask class to check that ICC$SRQ2 was started by the start method, and not in any other way (such as typing the transaction name on a terminal). If it was not started as intended, we abend with an "OOPS" abend code.
startQ->retrieveData();
We retrieve the start data that we were passed by ICC$SRQ1 and store within the IccStartRequestQ object for subsequent access.
buffer = startQ->data();
term->sendLine( "Start buffer contents = [%s]", buffer.dataArea() );
term->sendLine( "Start queue= [%s]", startQ->queueName() );
term->sendLine( "Start rtrn = [%s]", startQ->returnTransId().name());
term->sendLine( "Start rtrm = [%s]", startQ->returnTermId().name() );
The start data buffer is copied into our IccBuf object. The other start data items (queue, returnTransId, and returnTermId) are displayed on the terminal.
task()->delay( ti );
We delay for five seconds (that is, we sleep and do nothing).
startQ->setRouteOption( "ICC1" );
The setRouteOption signals that we will start on our caller's system (ICC1).
startQ->start( startQ->returnTransId(),startQ->returnTermId());
return;
We start a transaction called ITMP (the name of which was passed by ICC$SRQ1 in the returnTransId start information) on the originating terminal (where ICC$SRQ1 completed as it started this transaction). Having issued the start request, ICC$SRQ1 ends, by returning control to CICS.
Finally, transaction ITMP runs on the first terminal. This is the end of this demonstration of starting transactions asynchronously.
See Appendix C. Output from sample programs for the expected output from these sample programs.
[[ Contents Previous Page | Next Page Index ]]