When using the RI, do not use the ACMS-supplied agent (CP). Instead, use an RI agent to interface the task submitter to ACMS. An RI agent is provided as part of the ACMS software. You can use either this ACMS-supplied agent, called ACMS$RI_AGENT, or you can write your own agent to meet the specific needs of an application.
The ACMS$RI_AGENT provides an example of how an agent program can be developed to utilize the RI interface. An RI agent uses the Systems Interface (SI) services to sign users in to ACMS, enable the RI agent to perform I/O through the request interface, and call tasks in an ACMS application. The ACMS$RI_EXAMPLES directory contains a listing of the source code of the ACMS-supplied RI agent. See Compaq ACMS for OpenVMS Systems Interface Programming for more information about the Systems Interface and its services.
Always run an RI agent from a user process so there is one RI agent for each user process. An RI agent submits tasks to ACMS under the OpenVMS user name of the user process. The RI agent signs in each user process to identify it to the ACMS system. Just as in a standard ACMS system, only users authorized with the ACMS User Definition Utility can gain access to ACMS. Also, all terminals or devices accessing ACMS must be authorized with the ACMS Device Definition Utility. See Compaq ACMS for OpenVMS Managing Applications for more information about authorizing users and devices.
The RI agent ACMS$RI_AGENT (by default) prompts the user for an application and task name. An RI agent can also call a menu interface through which the user can enter data. You can write your own menu interface modules, or if you are interfacing to FMS, you might want to use the ACMS-supplied FMS menu interface. Section 14.5.1 describes more about how to provide a menu interface.
Figure 14-4 shows the pseudocode for the Request Interface agent and two menu interface routines. The routines in the figure use FMS calls to display the menu and retrieve the data.
Figure 14-4 Pseudocode for an RI Agent Using an FMS Menu Interface
In this figure, the RI agent:
While taking these steps to develop an agent, you may need to define several logical names and routines for use at run time. Table 14-1, Table 14-2, and Table 14-3 summarize these names and routines.
|Logical Name||Used by ACMS at Run Time|
|ACMS$RI_LIB_library-name||A logical defined by the user that identifies the request library or shareable image associated with the name used in a REQUEST IS USING clause.|
|ACMS$RI_MENU||A logical defined by the user that identifies the shareable image created by linking the ACMS$RI_MENU_INIT menu initialization procedure and the ACMS$RI_MENU_ROUTINE menu interface procedure.|
|ACMS$RI_LIB_CANCEL||An optional user-written cancel procedure that the RI calls to do cleanup work when a task is canceled.|
|ACMS$RI_DEBUG_ROUTINE||An ACMS-supplied routine that the Request Interface starts up when you debug URP object modules.|
|ACMS$RI_LIB_INIT||An optional user-written initialization procedure that sets up the necessary data structures for the RI executable image.|
|ACMS$RI_MENU_INIT||An optional user-written initialization procedure that sets up to use the ACMS$RI_MENU_ROUTINE menu interface.|
|ACMS$RI_MENU_ROUTINE||A user-written (URP) menu interface procedure.|
There are two ways to obtain task selection information from the user: write your own menu interface, or code the RI agent to prompt you automatically for information. If you choose not to write a menu interface and you use the ACMS-supplied RI agent, by default the ACMS$RI_AGENT prompts the user to enter the task and application selections. If you choose to use a menu interface, the ACMS$RI_AGENT can optionally call special-purpose menu interface (URP) procedures with which the user can enter the task and application information.
With a menu interface in place, the application is easier to use because you do not have to select an application and the specific task each time you want to run a task. To use a menu interface with the ACMS$RI_AGENT, a programmer must write a menu initialization procedure and a menu interface procedure. These procedures must be named ACMS$RI_MENU_INIT and ACMS$RI_MENU_ROUTINE, respectively.
Include these procedures in the RI agent code in one of the following ways:
If interfacing to FMS, you may want to use the ACMS-supplied FMS menu interface. ACMS supplies an FMS-based menu interface as part of the RI software. The sample FMS form library for the menu interface is located in the ACMS$RI_EXAMPLES directory.
As with the user-written menu interface described previously, you can include the ACMS-supplied FMS menu interface in an RI agent by either defining the logical ACMS$RI_MENU to point to a shared image that contains the ACMS$RI_MENU_INIT and ACMS$RI_MENU_ROUTINE procedures, or relinking the RI agent with the ACMS$RI_MENU_INIT and ACMS$RI_MENU_ROUTINE procedures.
The layout of the FMS menu form is similar to the ACMS menu format. The FMS menu form contains a menu header, a selection list, a prompt line and a message line. The menu header is the name of the menu. The selection list shows the tasks to run and the menus for display. The prompt line includes both the SELECTION: prompt and the blank spaces after the prompt. You type the number or keyword for the task or menu you want in the blank space after the prompt. Press [Return] after your selection.
Example 14-11 and Example 14-12 show FMS-supplied initialization and menu interface definitions.
|Example 14-11 FMS Initialization Procedure|
FUNCTION LONG ACMS$RI_MENU_INIT RET_STATUS = FDV$ATERM(TCA%(),12%,12%) RET_STATUS = FDV$AWKSP(FMS_WORKSPACE%(),2000%) RET_STATUS = FDV$LOPEN('ACMS$RI_FMS_MENU_LIB'm10%) END FUNCTION
|Example 14-12 FMS Menu Procedure|
FUNCTION LONG ACMS$RI_MENU_ROUTINE ( STRING TASK_NAME , & STRING APPLICATION_NAME, & LONG EXECUTION_STATUS ) RET_STATUS = FDV$CDISP(TRM$(CURRENT_FORM)) RET_STATUS = FDV$GET ( MENU_OPTION, TERMINATOR, 'OPTION') RET_STATUS = FDV$RETDI(VAL%(DATA_INDEX),NAMED_DATA) END FUNCTION
To change FMS menus, change only the form definition. You do not need
to make code changes to change FMS menus. The NAMED_DATA syntax is part
of FMS forms definition and is explained in the FMS documentation. For
more information about how to modify the ACMS-supplied FMS menu
interface to work with your application, see Appendix F.
14.5.2 Compiling and Linking Menu Interface URPs with the RI Agent
For example, type the following command to link the RI agent to include the FMS menu interface:
$ LINK/EXE=fmsagent.exe sys$input/option sys$library:acms$ri.olb/include=acms$ri_agent_module sys$library:acms$ri_fms_menu.olb/include= (acms$ri_menu_init, acms$ri_menu_routine) $ DEFINE ACMS$RI_LIB_libraryname ri_request_library.exe $ DEFINE ACMS$RI_FMS_MENU_LIB fmsformmenulib.flb $ RUN fmsagent
When you write a user-written menu routine for the ACMS$RI_AGENT, it is important to be aware of how your chosen language handles dynamic string descriptors. The task name and application name arguments in the ACMS$RI_AGENT are passed to the ACMS$RI_MENU_ROUTINE as dynamic descriptors. If the language you have chosen does not support dynamic string descriptors, you must use an OpenVMS run-time library routine to return the task and application names to the ACMS$RI_AGENT.
The following FORTRAN example accepts an application name and a task name into two fixed-length strings. The STR$TRIM OpenVMS RTL routine is then used to remove trailing spaces and copy the names into the arguments supplied by the ACMS$RI_AGENT.
! ! THIS ROUTINE GETS THE TASK AND APPLICATION ! NAMES FROM THE USER.... ! INTEGER FUNCTION ACMS$RI_MENU_ROUTINE(TASK,APPL,TASK_STS) ! ! Addresses of appl and task name dynamic string descriptors INTEGER*4 TASK, APPL ! ! Completion status of previous task (0 if 1st time through) INTEGER*4 TASK_STS ! ! Local strings to input application and task names CHARACTER*32 TNAME, ANAME ! ! RTL completion status INTEGER*4 STATUS ! ! RTL routine to trim spaces from a string INTEGER*4 STR$TRIM ! WRITE( UNIT=5,FMT='(A,$)' ) ' INPUT APPLICATION SELECTION: ' READ ( UNIT=5,FMT='(A32)' ) ANAME WRITE( UNIT=5,FMT='(A,$)' ) ' INPUT TASK SELECTION: ' READ ( UNIT=5,FMT='(A32)' ) TNAME ! STATUS = STR$TRIM( %REF(TASK), %DESCR(TNAME) ) IF (STATUS) THEN STATUS = STR$TRIM( %REF(APPL), %DESCR(ANAME) ) END IF ! ACMS$RI_MENU_ROUTINE = STATUS RETURN END
Section 14.6.1 discusses using the OpenVMS Debugger to debug applications that are already up and running, but are currently using TDMS requests. Section 14.6.2 describes using the ACMS Task Debugger to debug URPs and the tasks that they call.
Do the following to prepare to debug:
$ LINK/DEBUG/EXE=debug_agent - _$ sys$library:acms$ri.olb/include=acms$ri_agent_module
To protect business data, set up test files to run against the task. If
your procedures use logical names to identify the files used, create a
set of data files in another directory and temporarily redefine the
logical names to point to that directory. If defining these logical
names from DCL command mode, be sure to define the names as group or
system logicals using the /GROUP or /SYSTEM logical on the DEFINE or
14.6.1 Using the OpenVMS Debugger to Debug URPs Using a Running Application
Start with a running ACMS application that is currently working by using TDMS requests. Then define the ACMS$RI_LIB_library-name logical name to point to the URP shareable image file. Then run the RI agent you linked with the debugger. For example:
$ ACMS/START APPLICATION test_application $ DEFINE ACMS$RI_LIB_request_library1 request_lib_image.exe $ RUN debug_agent DBG> GO Task Name: Application Name: DBG>
In this example, test_application is a fully developed ACMS application
that contains a TDMS request library named request_library1.rlb. The
shareable image created to replace that TDMS request library is named
14.6.2 Using the ACMS Task Debugger to Debug URPs and Their Tasks
This section provides an outline of the steps to debug URPs and their tasks by using the ACMS Task Debugger. This method of debugging is very similar to the method for debugging tasks submitted by user-written agents that is discussed in Compaq ACMS for OpenVMS Writing Server Procedures. By following these instructions and supplementing this discussion with the one in Compaq ACMS for OpenVMS Writing Server Procedures, you can debug URPs with the RI debugger and debug tasks with the ACMS Task Debugger. To use this debugging method, do the following:
$ SET PROCESS/PRIVILEGE=SHARE $ ACMS/DEBUG/AGENT_HANDLE=dummyapplicationname testgroup.tdb ACMSDBG>
$ DEFINE ACMS$RI_LIB_request_library1 request_lib_image.exe $ DEFINE ACMS$DEBUG_AGENT_TASK "TRUE" $ RUN debug_agent DBG> GO Task Name: Application Name: dummyapplicationname DBG>
After setting up the debugger process, start the agent process and enter the GO command at the DBG> prompt. Because a menu interface was not linked into the RI agent in this example, the ACMS$RI_AGENT prompts you for a task name and an application name.
After you enter the task and application names, the RI determines if the RI request library shareable image file contains the ACMS$RI_DEBUG_MODULE procedure (URP). If the debugger procedure exists, the OpenVMS debugger (DBG>) prompt appears.
At this point, use the SET IMAGE command to tell the debugger that you are going to use the RI request library shareable image file. The name of the image specified with this command must be the same as the logical name used to point to the RI request library image. Then you can set breakpoints at any URPs, including the initialization and cancellation URPs. For example:
DBG> SET IMAGE ACMS$RI_LIB_<!OPEN>requestlibraryname<!CLOSE> DBG> SET BREAK urp1 DBG> SET BREAK urp2 DBG> GO
Type $EXIT in response to the "Enter Task Name:" prompt to
exit from the RI agent.
14.7 Defining an Application that Uses the Request Interface
There are no differences between an application definition that uses DECforms or TDMS and one that uses the Request Interface. Example 14-13 shows the application definition that uses the task group and tasks defined in this document.
|Example 14-13 Example Application Definition|
REPLACE APPLICATION RI_SAMPLE_APPL AUDIT; APPLICATION USERNAME IS adf$exc; DEFAULT APPLICATION FILE IS "ACMS$RI_EXAMPLES:RI_SAMPLE_APPL.ADB"; SERVER DEFAULTS ARE AUDIT; USERNAME IS adf$server; END SERVER DEFAULTS; TASK DEFAULTS ARE AUDIT; END TASK DEFAULTS; TASK GROUP IS RI_LOGICAL_GROUP: TASK GROUP FILE IS "ACMS$RI_EXAMPLES:RI_PASSED_GROUP.TDB"; END TASK GROUP; END DEFINITION;
To run your agent in a production environment, relink the request procedures, omitting the /DEBUG qualifier and the RI debug object module ACMS$RI_DEBUG_MODULE. Then use the DCL RUN command followed by the name of the RI agent image. For example:
$ RUN ACMS$RI_AGENT