[an error occurred while processing this directive]

HP OpenVMS Systems Documentation

Content starts here

Compaq ACMS for OpenVMS
Writing Applications


Previous Contents Index

14.3.1 Task Definition

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:

  1. At application startup time, the EXC determines the file type of the request libraries (.RLB or .EXE). It opens the ACMS$RI_EXAMPLES:RI_REQUEST_LIBRARY2.RLB file but does not open the ACMS$RI_EXAMPLES:RI_REQUEST_LIBRARY1.EXE file.
    If there is an ACMS$RI_LIB logical name that redefines the .EXE file to be an .RLB file, the Request Interface opens that request library at run time. See Section 14.3.3 for information on defining the ACMS$RI_LIB logical name.
  2. When the task step begins executing, the EXC passes the following names to the RI agent:
    • RI_REQUEST_LIBRARY1
    • RI_REQUEST_LIBRARY2
      The image activation for a shareable image (.EXE) occurs only the first time a URP in that image is needed. After that, the image stays active; only a call to the procedure is necessary.
  3. The Request Interface does the following:
    • Translates the logical name ACMS$RI_LIB_RI_REQUEST_LIBRARY1 and uses the file type of the resulting translation to determine whether to call a user request procedure from a shareable image or a request from a TDMS request library. In this example, if no logical name has been defined, the Request Interface calls the RI_INQ_REQUEST user request procedure from the RI_REQUEST_LIBRARY1.EXE shareable image file.
    • Translates the logical name ACMS$RI_LIB_RI_REQUEST_LIBRARY2 and uses the file type of the resulting translation to determine whether to call a user request procedure from a shareable image or a request from a request library. In this example, if no logical name has been defined, the Request Interface calls the RI_DISP_INQ_REQUEST request from the RI_REQUEST_LIBRARY2.RLB request library.

14.3.3 How and When to Use the ACMS$RI_LIB Logical Name

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:

  • When defining a task whose exchange steps call only URPs, name the URP executable images (.EXE) in the task group.
  • When defining a task whose exchange steps call only TDMS, name the TDMS request libraries (.RLB) in the task group.
  • When defining a task whose exchange steps call TDMS requests and also call URPs, name the TDMS request library in the task group, and use the ACMS$RI_LIB logical name to point to URP executable images where necessary.

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:

  • The name of the URP must correspond exactly to the name used for the request in the task definition. For example, the function name in BASIC or FORTRAN or a COBOL PROGRAM-ID must match the request name in the task definition. In Example 14-1, the URP request name is RI_INQ_REQUEST.
  • The workspaces named in the URP parameter list must be in the same order as those listed for the exchange step in the task definition.
  • As an option, include an initialization procedure in an RI shared image. If you provide one, ACMS calls this procedure the first time it calls a URP in the shared image. For example, you can use an initialization procedure to open a channel to a device or open an FMS form file.
  • You can also optionally provide a cancellation procedure in an RI shared image. If you provide one, ACMS will call it if it must cancel a task that is calling a URP in the shared image at the time of the cancellation.
  • Considerations for the URP shareable image:
    • Link the URP into a shared image and make sure the image is position independent.
    • Set the protection of the shareable image file to have read and execute access.

    The RI agent activates the URP shareable image only once, and it remains mapped into the agent's memory until the agent image exits.
  • Each URP procedure must return a status value or you will receive the message "Error processing request interface call."
  • ACMS only caches .RLB files that are defined in the task group. It does not cache .RLB files defined by an ACMS$RI_LIB logical. ACMS never caches RI .EXE files.

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;

14.4.1 Writing an ACMS$RI_LIB_INIT Initialization Procedure

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:

  • Reports an error ("Error Processing request interface call") and cancels the task
  • Is unable to record the exact error message in the ACMS audit trail log

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

14.4.2 Writing an ACMS$RI_LIB_CANCEL Cancellation Procedure

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

14.4.3 Compiling and Linking URPs

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:

  • In the REQUEST LIBRARY IS clause of the definition of each task group whose tasks call URPs
  • By defining the ACMS$RI_LIB logical name to point to the URP shareable image file

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:

  • Name the ACMS$RI_DEBUG_MODULE object module in the LINK command if you want to test a URP in the debugger.
  • Use an options file to declare all URP names as universal and common data as nonshared. See Example 14-8 for an example of an options file on OpenVMS VAX and Example 14-9 for an example of an options file on OpenVMS Alpha.

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:

  • The image must be a shareable image. Therefore, always link URPs as a shareable image.
  • The names of all URPs, including ACMS$RI_DEBUG_ROUTINE, ACMS$RI_LIB_INIT, and ACMS$RI_LIB_CANCEL, must be universal symbols.
  • All common (global) areas defined as shareable between the URPs must not be shareable by different processes, and must be declared nonshareable in an options file. Every process can share the RI request library shareable image code but must have its own copy of common data areas.

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:

  1. The /SHARE qualifier creates an OpenVMS shareable image. If you forget this qualifier and attempt to use the image, the RI logs the error "Reserved addressing fault" in the ACMS audit trail log to notify you that the image has not been linked as a shareable image.
  2. The UNIVERSAL command in the options file on a VAX system sets up the global symbols as keys into the image. The SYMBOL_VECTOR command in the options file on an Alpha system sets up the global symbols as keys into the image. The symbols referenced must be global to be defined as universal. You define a symbol as universal on VAX by using the UNIVERSAL command and on Alpha by using the SYMBOL_VECTOR command. All URPs, including the initialization, debugger, and cancellation URPs, must be defined as universal symbols. If you try to access a URP that was not declared as a universal symbol, the RI logs the following error in the ACMS audit trail log:


    %LIB-F-KEYNOTFOU, key not found in tree
    
  3. The PSECT_ATTR command in the option file sets the URP common area as not shareable. By default, all common areas have the PSECT attribute SHR. This attribute lets multiple processes share the same data area if it is installed (using the OpenVMS Install Utility) as writable.
    Be sure that all URPs for a given RI request library can share the data areas. However, those data areas should not be shareable across different processes. If you define the PSECT attribute as NOSHR, each user (process) can have a separate copy of the data area. If you try to run the RI with the PSECT attribute set to SHR, the RI logs an error in the ACMS audit trail log, notifying you that the image must be installed as WRITABLE. This message indicates that the PSECT attribute is set to SHR. Remember, if you install the image as writable, the data areas are shared by many processes and the URPs may access corrupted data.


Previous Next Contents Index