Previous | Contents | Index |
The task definition in Example 14-1 is an example of a simple inquiry task. This task definition is generic in that it can be used to call a TDMS request or a URP in a shareable image. This discussion provides the task definition for the sake of example. This example is part of the ACMS-supplied example that is provided in the ACMS$RI_EXAMPLES directory. It is also referred to in several subsequent sections.
The task definition consists of two exchange steps and a processing step. In this task, the user enters a customer number and presses [Return]. The task uses the customer number to read the customer data file and retrieve the appropriate record, displaying that record on the screen.
Example 14-1 Simple Inquiry Task |
---|
REPLACE TASK RI_INQ_TASK DEFAULT SERVER IS RI_SERVER; WORKSPACES ARE RI_EMPLOYEE_RECORD; BLOCK WORK EX1: EXCHANGE REQUEST IS RI_INQ_REQUEST IN RI_REQUEST_LIBRARY1 USING RI_EMPLOYEE_RECORD; SP1: PROCESSING CALL RI_GET_PROCEDURE IN RI_SERVER USING RI_EMPLOYEE_RECORD; EX2: EXCHANGE REQUEST IS RI_INQ_DISP_REQUEST IN RI_REQUEST_LIBRARY2 USING RI_EMPLOYEE_RECORD; END BLOCK WORK; END DEFINITION; |
In this example, the task calls a request in a library identified as REQUEST_LIBRARY1. Note that this does not indicate whether ACMS should use a TDMS request or a URP. This decision is not made until run time, when the RI calls a TDMS request or a URP depending on how the library is defined in the group and whether or not an ACMS$RI_LIB logical has been defined for this library.
In a single task, one exchange step can call a URP to do terminal I/O while another can use a TDMS request to do terminal I/O. ACMS passes workspaces to URPs in the same way that it passes workspaces to routines in procedure servers.
See Chapter 10 for more information on defining a task.
14.3.2 Defining a Task Group
When defining a task group whose tasks call only URPs, you can use the REQUEST LIBRARY IS clause to name the shareable image containing URP procedures. Example 14-2 shows an example of a task group definition. Alternatively, you can name an .RLB file and use an ACMS$RI_LIB logical name to point to a shareable image at run time. See Chapter 10 for more information on defining a task group.
Example 14-2 Task Group Definition |
---|
REPLACE GROUP RI_PASSED_GROUP REQUEST LIBRARY ARE "ACMS$RI_EXAMPLES:RI_REQUEST_LIBRARY1.EXE" WITH NAME RI_REQUEST_LIBRARY1, "ACMS$RI_EXAMPLES:RI_REQUEST_LIBRARY2.RLB" WITH NAME RI_REQUEST_LIBRARY2; DEFAULT TASK GROUP FILE IS "ACMS$RI_EXAMPLES:RI_PASSED_GROUP.TDB"; SERVER IS RI_SERVER: PROCEDURE SERVER IMAGE IS "ACMS$RI_EXAMPLES:RI_SERVER.EXE"; INITIALIZATION PROCEDURE IS RI_INIT_PROCEDURE; TERMINATION PROCEDURE IS RI_TERM_PROCEDURE; PROCEDURES ARE RI_ADD_PROCEDURE, RI_GET_PROCEDURE; END SERVER; TASK IS RI_ADD_TASK : TASK DEFINITION IS RI_ADD_TASK; RI_INQ_TASK : TASK DEFINITION IS RI_INQ_TASK; END TASK; END DEFINITION; |
Notice that this task group names both a URP shareable image file and a request library; the tasks in the group can use both user request procedures and TDMS requests.
However, be aware that you cannot use CP to select a task that uses a request in a library that is defined as an .EXE file. This is because CP cannot call URPs and does not translate ACMS$RI_LIB logical names in order to determine if an .RLB file is also available.
Consider the steps ACMS takes when processing the task and task group shown in Example 14_1 and Example 14-2:
The TDMS request libraries (.RLB) files or the URP (.EXE) shareable image files can be defined and referenced in the REQUEST LIBRARY IS clause in the task group definition or with the ACMS$RI_LIB_libraryname logical. In either case, the ACMS$RI_LIB logical name can replace or override whatever is defined in the task group definition.
The ACMS shareable image, ACMRRSHR (in the RI agent process), translates the ACMS$RI_LIB logical name at run time to determine whether the task should use TDMS or a URP. Define the ACMS$RI_LIB logical name in any logical name table that is accessible by the RI agent program. For example, defining it as a process logical name means that only a specific user has access to the request library or shareable image defined by the logical. However, defining it as a group logical name means that all users with the same UIC group can have access to the request library or shareable image file defined by the logical.
You use the DEFINE command to define the logical name ACMS$RI_LIB_file-name for a shareable image or request library. It is important that the request library that is referenced by the ACMS$RI_LIB logical name has the same library name as defined in the task group definition, and it must include the .RLB or .EXE file extension:
$ DEFINE ACMS$RI_LIB_RI_REQUEST_LIBRARY1 - _$ ACMS$RI_EXAMPLES:RI_REQUEST_LIBRARY1.EXE/GROUP |
This example defines a group logical for the shareable image named
RI_REQUEST_LIBRARY1.EXE. When defining the ACMS$RI_LIB logical, provide
the full file specification. Otherwise, ACMS assumes the file is
located in SYS$SHARE.
If you use TDMS applications with the RI, you do not need to make any modifications to existing task, task group, or application definitions. However, try to avoid misleading other users by what you have defined in the task definition. Consider the following options to improve the readability of a task group definition:
Remember that ACMS makes the final determination at run time to call a
TDMS request or a URP. You can use the ACMS$RI_LIB logical to override
what is defined in the task group definition. Use this logical to
enable or disable the RI on a user-by-user basis so that you can have
one person use TDMS and another use a URP in the same ACMS application.
This makes the RI attractive for testing an application because you can
use logicals to redefine the RLB that is hard-coded in the task group
definition.
14.4 Writing User Request Procedures
Write user request procedures, URPs, to perform I/O for ACMS tasks in place of TDMS requests. You can write a URP in any OpenVMS-supported high-level language and include the necessary facility calls (for example, FMS, SMG, QIO) that allow you to interface ACMS with the appropriate device.
A URP can use all the facilities available to a normal program and extend the terminal I/O capabilities of the ACMS application without impacting the task definition or task group definition. Use the following guidelines when writing RI procedures:
Example 14_1 and Example 14-2 depict a task and a task group in which the first exchange step in the task calls a URP. Example 14-3 shows RI_INQ_REQUEST, a FORTRAN URP that displays the inquiry form and prompts the user to enter the customer number.
Example 14-3 FORTRAN User Request Procedure |
---|
!********************** RI_INQ_REQUEST ******************* ! INTEGER FUNCTION RI_INQ_REQUEST (DATA_REC) INCLUDE '($IODEF)' !OpenVMS I/O definitions ! ! Declaration of variables ! ! Declare external routines ! INTEGER SYS$QIOW ! ! Declare the workspaces that will be passed as parameters ! STRUCTURE /RI_EMPLOYEE_RECORD/ INTEGER*4 EMPLOYEE_ID CHARACTER*10 EMPLOYEE_FIRST_NAME CHARACTER*10 EMPLOYEE_LAST_NAME END STRUCTURE RECORD /RI_EMPLOYEE_RECORD /DATA_REC ! ! Declare the IOSB to be used in the OpenVMS QIO system service ! STRUCTURE /IOSTAT_BLOCK/ INTEGER*2 IOSTAT INTEGER*2 TERM_OFFSET INTEGER*2 TERMINATOR INTEGER*2 TERM_SIZE END STRUCTURE RECORD /IOSTAT_BLOCK/ IOSB ! ! Declare input channel number to be shareable ! by all User Request Procedures (URP). ! INTEGER*2 INPUT_CHAN COMMON /INPUT_CHANNEL/INPUT_CHAN ! ! Declare local variables ! INTEGER*4 CODE,STATUS CHARACTER*1 ESC DATA ESC /27/ CHARACTER*3 CLEAR DATA CLEAR /'[2J'/ CHARACTER*7 POSITION DATA POSITION /'[00;24f'/ CHARACTER*80 PROMPT CHARACTER*10 INPUT_STRING ! ! Perform the RI_INQ_REQUEST User Request Procedure. This ! routine will duplicate the work done by the RI_INQ_REQUEST ! TDMS request, which displays a form to accept employee id from ! the terminal user. ! ! Set return status success ! RI_INQ_REQUEST = 1 ! ! Screen is cleared and cursor is positioned at 6th line, ! 24th column then user is requested to input Employee ID. ! POSITION(2:3) = '06' PROMPT = ESC//CLEAR//ESC//POSITION//'EMPLOYEE ID: ' CODE = IO$_READVBLK.OR.IO$_READPROMPT STATUS = SYS$QIOW (,%VAL(INPUT_CHAN), %VAL(CODE),IOSB,,, 1 %REF(INPUT_STRING), %VAL(6),,, 1 %REF(PROMPT), %VAL(25)) IF (.NOT. STATUS) THEN RI_INQ_REQUEST = STATUS RETURN END IF ! ! Employee ID is converted from a string to the integer ! field in the workspace record. ! DECODE (IOSB.TERM_OFFSET,100,INPUT_STRING) DATA_REC.EMPLOYEE_ID 100 FORMAT (I6) END |
Example 14-4 shows RI_INQ_DISP_REQUEST, a TDMS request used in the second exchange step of the task shown in Example 14-1.
Example 14-4 TDMS Request |
---|
REPLACE REQUEST RI_INQ_DISP_REQUEST FORM IS RI_INQ_DISP_FORM; RECORD IS RI_EMPLOYEE_RECORD; CLEAR SCREEN; DISPLAY FORM RI_INQ_DISP_FORM; OUTPUT EMPLOYEE_ID TO EMPLOYEE_ID, EMPLOYEE_FIRST_NAME TO EMPLOYEE_FIRST_NAME, EMPLOYEE_LAST_NAME TO EMPLOYEE_LAST_NAME; WAIT; END DEFINITION; |
As an option, you can write an initialization procedure that sets up the necessary data structures for the RI shared image. For example, if the URP use an FMS-supported device, the initialization procedure might set up FMS workspaces, open an I/O channel to the terminal, open forms libraries, and do other initialization work necessary to perform I/O to the terminal. The initialization procedure must return a status value, or the RI reports a failure and cancels the current task.
The ACMSRRSHR component calls the ACMS$RI_LIB_INIT procedure only once (when it first maps the shared image) before it calls a URP in the shared image for the first time. Always name this procedure ACMS$RI_LIB_INIT. Link the initialization procedure with the shared image.
Example 14-5 shows an initialization procedure written in FORTRAN.
Example 14-5 FORTRAN Initialization Procedure |
---|
!**************** ACMS$RI_LIB_INIT ********************** ! INTEGER FUNCTION ACMS$RI_LIB_INIT ! ! This procedure is the initialization routine for the TDMS_LIB ! library file. The initialization procedure is not required, ! but if one exists it must be named ACMS$RI_LIB_INIT. ! ! Since this library file will perform QIOs to the terminal ! instead of executing the normal TDMS request for each exchange ! step, the initialization procedure will open a channel to ! the user terminal. ! ! Declaration of variables ! ! Declare external routines ! INTEGER SYS$ASSIGN ! ! Declare input channel number to be shareable ! by all User Request Procedures (URP). ! INTEGER*2 INPUT_CHAN COMMON /INPUT_CHANNEL/INPUT_CHAN ! ! Set up local variables ! INTEGER*4 STATUS ! ! **IMPORTANT: ! A status must be passed back from the initialization procedure ! or the RI will report a failure and cancel the current task. ! ! Set the return status equal to success, ! ACMS$RI_LIB_INIT = 1 ! ! Perform the initialization procedure for the QIO ! library file. ! ! Assign the terminal pointed to by SYS$INPUT and provide ! the I/O channel number to perform subsequent QIO calls. ! STATUS = SYS$ASSIGN ('SYS$INPUT',INPUT_CHAN,,) ! ! Check the status that was return from the ! SYS$ASSIGN system service call. If an error ! occurred, then return the error to the Request ! Interface which will report the error in ! ACMS audit log and cancel the task. ! IF (.NOT. STATUS) THEN ACMS$RI_LIB_INIT = STATUS RETURN END IF END |
The name of the URP in this example is in a function statement. The URP does not pass any parameters, but it defines a COMMON area with which to open a channel to a user terminal. This initialization URP sets the return status to success. When using the RI, it is important to return a status from the URP whether it is an initialization URP or any other URP. The RI agent checks the status returned. If there is an error, the message is returned to the RI. The RI reports the error to ACMS, cancels the current task, and logs the message in the ACMS audit trail log. If you do not return status information from a URP, the RI agent:
Example 14-6 shows an example of the error messages that would be recorded in the audit trail log if the RI agent was unable to open the I/O channel for the RI_INQ task.
Example 14-6 Example of Audit Trail Error Messages |
---|
Task canceled in STEP EX1 task RI_INQ_REQUEST in Group RI_PASSED_GROUP Error processing request interface call Error executing initialization routine for request library file DEVICE:$[$DIR]LIBRARY1.EXE PROGRAM ERROR: Error processing request interface call Error in Request RI_INQ_REQUEST, error returned from URP in DEVICE:$[$DIR]LIBRARY1.EXE SYSTEM-F-INVCHAN, invalid I/O channel |
You can optionally write a cancel procedure to abort any I/O in progress and do any necessary cleanup work for a task. If a task is canceled for any reason such as by the ACMS/CANCEL operator command (discussed in Compaq ACMS for OpenVMS Managing Applications), the Request Interface searches for the ACMS$RI_LIB_CANCEL routine in the shareable image and uses that routine as the cancellation procedure for the task. Example 14-7 shows a cancellation procedure written in FORTRAN.
Example 14-7 FORTRAN Cancel Procedure |
---|
!****************** ACMS$RI_LIB_CANCEL *********************** ! INTEGER FUNCTION ACMS$RI_LIB_CANCEL ! ! This procedure is the cancellation routine for the TDMS_LIB ! library file. The cancellation procedure is not required, ! but if one exists it must be named ACMS$RI_LIB_CANCEL. ! ! This routine will get called when the current task gets ! canceled either by the operator command "ACMS/CANCEL TASK" ! or the using typing [Ctrl] during an exchange step. It ! signals an ACMS$_CANCELD error, which will abort any ! QIO's that were in progress and will unwind the call ! stack. ! ! Declaration of variables ! ! Declare external symbols and routines ! EXTERNAL ACMS$_CANCELD INTEGER LIB$SIGNAL,SYS$CANCEL ! ! Declare input channel number to be shareable ! by all User Request Procedures (URP). ! INTEGER*2 INPUT_CHAN COMMON /INPUT_CHANNEL/INPUT_CHAN ! ! Declare local variables ! INTEGER*4 STATUS ! ! Perform the cancellation procedure for the TDMS_LIB ! library file. ! ! Cancel any QIO that is outstanding ! STATUS = SYS$CANCEL(%VAL(INPUT_CHAN)) CALL LIB$SIGNAL(ACMS$_CANCELD) ! END |
After writing the user request procedures for all the tasks in a task group and any initialization and cancellation procedures, compile those procedures and link them into a shareable image file. Reference the shareable image file in either of the following ways:
An application can use multiple shareable image files. Each shareable image file contains any number of URPs, an optional URP initialization procedure to set up the necessary work areas, and an optional URP cancellation procedure. Figure 14-3 shows the contents of a shareable image file.
Figure 14-3 User-Written Shareable Image File
The following command compiles request procedures RI_INQ_REQUEST, ACMS$RI_LIB_INIT, and ACMS$RI_CANCEL, and produces three object modules:
FORTRAN RI_INQ_REQUEST, ACMS$RI_LIB_INIT, ACMS$RI_LIB_CANCEL/DEBUG |
When linking your request procedures, you must:
Example 14-8 REQPROCS.OPT Options File on VAX |
---|
UNIVERSAL = RI_INQ_REQUEST UNIVERSAL = ACMS$RI_DEBUG_ROUTINE UNIVERSAL = ACMS$RI_LIB_INIT UNIVERSAL = ACMS$RI_LIB_CANCEL PSECT_ATTR = INPUT_CHANNEL,PIC,USR,OVR,REL,GBL,NOSHR,NOEXE,RD,WRT,NOVEC |
Example 14-9 REQPROCS.OPT Options File on Alpha |
---|
SYMBOL_VECTOR = (RI_INQ_REQUEST = PROCEDURE,- ACMS$RI_DEBUG_ROUTINE = PROCEDURE ,- ACMS$RI_LIB_INIT = PROCEDURE ,- ACMS$RI_LIB_CANCEL = PROCEDURE) PSECT_ATTR = INPUT_CHANNEL,PIC,USR,OVR,REL,GBL,NOSHR,NOEXE,RD,WRT,NOVEC |
The RI uses the OpenVMS Run-Time Library (RTL) routine LIB$FIND_IMAGE_SYMBOL to locate the URP to call. Therefore, the request library executable image must meet the following requirements of the LIB$FIND_IMAGE_SYMBOL routine:
You can use any OpenVMS file names for your procedures and for the shareable image file.
Example 14-10 links into a shareable image the four object modules. It also shows how to use the options file in Example 14-8 and Example 14-9 and how to meet the requirements of the LIB$FIND_IMAGE_SYMBOL RTL service.
Example 14-10 Linking Shareable Images and Using an Options File |
---|
$ LINK/DEBUG/SHARE/EXECUTABLE=REQPROCS.EXE RI_INQ_REQUEST, - _$ ACMS$RI_LIBINIT, ACMS$RI_LIB_CANCEL, - _$ SYS$LIBRARY:ACMS$RI.OLB/INCLUDE=ACMS$RI_DEBUG_MODULE, - _$ REQPROCS.OPT |
In this list of commands:
%LIB-F-KEYNOTFOU, key not found in tree |
Previous | Next | Contents | Index |