Previous | Contents | Index |
Using this method, you return a status indicator that is processed by the form in a field in a user-defined workspace. See Section 3.3.2 for more information on returning status in a field in a user-defined workspace.
The advantage of this method is that you do not need to use message files or OpenVMS system services or RTL routines to return error messages to users. The disadvantage is that you must always modify the form if you need to change the format of an error message.
To use hard-coded messages in the form, follow these steps:
step_status DATATYPE TEXT 8. |
MOVE "DUPLICAT" TO step_status OF task_control. GO TO 999-end. |
task_ctrl_wksp::step_status = "DUPLICAT" EXIT FUNCTION |
PROCESSING WORK IS CALL pers_add_employee_proc USING task_control, employee_record ACTION IS IF ( task_control.step_status <> "SUCCESS" ) THEN GOTO STEP get_new_employee_data; END IF; |
Using this method, you construct the complete error message directly in the step procedure. You use literal message text stored in the procedure, formatting variable error messages, if necessary.
The advantage of this method is that you do not need to use message files or OpenVMS system services or RTL routines to return error messages to users. The disadvantage is that you must always modify and recompile the step procedure and relink the procedure server image if you need to change the format of an error message.
To use hard-coded messages in a step procedure, follow these steps:
task_status_msg DATATYPE TEXT 80. |
* * Format 'Employee already exists' error message. * MOVE SPACES TO task_status_msg. STRING "Employee ID: " DELIMITED BY SIZE emp_badge_number DELIMITED BY " " " (last name: " DELIMITED BY SIZE emp_last_name DELIMITED BY " " ") already exists on file" DELIMITED BY SIZE INTO task_status_msg. SET status-result TO FAILURE. GO TO 999-end. |
! ! Format 'Employee already exists' error message. ! task_ctl_rec::task_status_msg = & "Employee ID: " + & emp_rec::emp_badge_number + & " (last name: " + & TRM$( emp_rec::emp_last_name ) + & ") already exists on file" EXIT FUNCTION 0 |
PROCESSING WORK IS CALL pers_add_employee_proc USING task_control, employee_record ACTION IS IF ( ACMS$T_STATUS_TYPE = "B" ) THEN GOTO STEP get_new_employee_data; END IF; |
In some cases, rather than returning errors for the action part of a step to handle, you can let the exception handler part of a step deal with errors. If your task is designed in this way, you need to raise an exception from your step procedure. ACMS supplies three services that raise different kinds of exceptions:
The ACMS exception services differ in an important way from the superseded ACMSAD$REQ_CANCEL service. Whereas the ACMSAD$REQ_CANCEL service immediately cancels the current task and does not return control to the step procedure, the ACMS exception services all return control to the step procedure after setting the appropriate exception condition. This allows the step procedure to clean up any context in the server and to complete normally.
Allowing the step procedure to complete before raising the exception in the task means that ACMS does not have to interrupt the server process. Therefore, if a step procedure uses one of the exception services to raise an exception, and you have specified that your server is to be run down on cancel only if it is interrupted, ACMS does not need to run down the server process. See Section 2.3 for details on how to specify when ACMS should run down your server.
Because step exceptions, transaction exceptions, and nonrecoverable exceptions are not raised in the task until the step procedure completes, have the step procedure return as soon as possible after raising an exception.
You can handle task execution errors in the exception handler part of a step, as explained in Compaq ACMS for OpenVMS Writing Applications. This manual discusses how to raise exceptions only in step procedures.
Step procedures can raise the following recoverable exceptions:
Following are explanations and examples of the two ACMS services that step procedures use to raise recoverable exceptions.
CALL "ACMS$RAISE_STEP_EXCEPTION" USING BY REFERENCE RET-STAT. |
SQL_ERROR_HANDLER. IF (RDB$LU_STATUS = RDB$_DEADLOCK) OR (RDB$LU_STATUS = RDMS$_DEADLOCK) OR (RDB$LU_STATUS = RDB$_LOCK_CONFLICT) OR (RDB$LU_STATUS = RDMS$_LCKCNFLCT) OR (RDB$LU_STATUS = RDMS$_TIMEOUT) THEN CALL "ACMS$RAISE_TRANS_EXCEPTION" USING BY REFERENCE ACMS$_TRANSTIMEDOUT ELSE CALL "LIB$CALLG" USING BY REFERENCE Rdb$MESSAGE_VECTOR, BY VALUE LIB$SIGNAL CALL "ACMS$RAISE_NONREC_EXCEPTION" USING BY REFERENCE RDB$LU_STATUS END-IF. |
Chapter 9 contains reference information regarding recoverable
exception services.
3.4.2.2 Raising Nonrecoverable Exceptions in Step Procedures
ACMS raises a nonrecoverable exception under the following conditions:
ACMS always runs down a server process if a step procedure generates a fatal OpenVMS exception condition. |
CALL "ACMS$GET_TID" USING CS-TID GIVING ret-stat. IF ret-stat IS NOT SUCCESS THEN CALL "ACMS$RAISE_NONREC_EXCEPTION" USING ret-stat. GO TO 999-end. |
One of the major advantages of implementing an application with ACMS is that you can easily separate your terminal I/O from your database I/O by performing all terminal I/O in exchange steps and all database I/O in processing steps. Following these guidelines has many advantages; two of the major ones are better performance and the ability to distribute tasks over multiple nodes.
Application developers find, however, that some situations require them to do terminal I/O in a processing step---for example, if they are incorporating an existing program into an application. Sometimes it is simpler to make an existing program a single-step task that does terminal I/O than to convert the program to a multiple-step task, which requires removing the terminal I/O from the program and placing it in exchange steps. For this reason, although it is not recommended, ACMS supports doing terminal I/O from processing steps. This section describes the limitations and restrictions involved.
ACMS does not automatically associate a terminal channel with the server process. If a procedure is to do terminal I/O, it must open and close the channel it uses each time it is called. The terminal channel cannot be retained across processing steps, even if the task retains server context. If the procedure does not close the channel before it completes, ACMS cancels the task and runs down the server process.
For a server process to perform terminal I/O, the task must pass the terminal to that process. In single-step tasks, the default is to pass the terminal to the server process. In multiple-step tasks, however, the default is not to pass the terminal to the server process, regardless of whether the server is a DCL server or a procedure server.
In multiple-step tasks, therefore, the task definition must use the TERMINAL I/O phrase for any processing step that does terminal I/O. (When used as an attribute on a processing step, TERMINAL I/O and REQUEST I/O are equivalent; however, REQUEST I/O as a processing step attribute is a declining feature and is, therefore, discouraged.)
Because distributed tasks cannot perform terminal I/O in processing steps, you cannot distribute a task that contains TERMINAL I/O (or REQUEST I/O) syntax in a processing step of the task definition. |
Because the procedure must open and close the terminal channel, there are several restrictions on the kinds of statements used for terminal I/O from a procedure server. Keep in mind the following considerations:
This chapter explains how to write step procedures that access several of the resource managers you can use with ACMS applications: Rdb using SQL, and Rdb using RDO, DBMS, and RMS.
The primary example in the chapter shows how to access an Rdb database using SQL with a procedure that participates in a distributed transaction. Examples showing how to access other resource managers supported by ACMS with distributed transactions are partial; they contain only syntax that is different from the SQL example.
The COBOL step procedure that is the principal example in this chapter is part of the AVERTZ Sample Application. The step procedure VR_COMPLETE_CHECKOUT_PROC participates in a distributed transaction that starts and ends in the parent task. Figure 4-1 shows where VR_COMPLETE_CHECKOUT_PROC fits into the AVERTZ Sample Application. The figure shows the ACMS menu, from which users can select the Reservation Task or the Checkout Task as two of three tasks displayed on the menu. Both the Reservation Task and the Checkout Task can call the Complete Checkout Task, which, in turn, calls the procedure VR_COMPLETE_CHECKOUT_PROC.
See Compaq ACMS for OpenVMS Concepts and Design Guidelines for a description of the AVERTZ sample application and Compaq ACMS for OpenVMS Writing Applications for a description of VR_COMPLETE_CHECKOUT_TASK. For further explanation of VR_COMPLETE_CHECKOUT_PROC. see Section 4.1.
Figure 4-1 Calling the Procedure VR_COMPLETE_CHECKOUT_PROC
This section describes how to write step procedures using the Structured Query Language (SQL) interface to Rdb. The techniques used with SQL are similar to those used in developing tasks and server procedures using Relational Data Manipulation Language (RDML), developed by Digital Equipment Corporation.
See the SQL documentation for general information regarding SQL.
The main example in this chapter, shown in Example 4-7, is a COBOL step procedure called VR_COMPLETE_CHECKOUT_PROC, which accesses an Rdb database using SQL. The procedure is part of the AVERTZ sample application.
Example 4-1 is part of the Complete Checkout Task, which calls the procedure VR_COMPLETE_CHECKOUT_PROC in the AVERTZ Sample Application. When checking out a car, the customer has the option of canceling the reservation. If the customer chooses to cancel the reservation, the task calls a procedure to perform the cancel processing. Otherwise, the task calls a procedure to complete the reservation. The task definition, in a simplified version, performs the following steps, which are also numbered in the example.
Example 4-1 Task Definition that Calls Server Procedures Using SQL |
---|
REPLACE TASK avertz_cdd_task:vr_complete_checkout_task USE WORKSPACES vr_control_wksp, . . . TASK ARGUMENTS ARE vr_sendctrl_wksp WITH ACCESS READ, . . . BLOCK WORK WITH TRANSACTION NO I/O ! perform: !+ !- ! Perform the checkout process or cancel the reservation depending ! on the user's choice. ! PROCESSING SELECT FIRST TRUE (vr_control_wksp.ctrl_key = "OK"): (1) CALL PROCEDURE vr_complete_checkout_proc IN vr_update_server USING vr_reservations_wksp, vr_vehicles_wksp, vr_control_wksp; (vr_control_wksp.ctrl_key = "CANCL"): (2) CALL PROCEDURE vr_cancel_rs_proc IN vr_update_server USING vr_reservations_wksp, vr_control_wksp; END SELECT; . . . ! Write to the history record to record the completion of the checkout or the ! the cancellation of the reservation. ! PROCESSING (3) CALL PROCEDURE vr_write_hist_record_proc IN vr_log_server USING vr_hist_wksp, vr_reservations_wksp; . . . ! END BLOCK; ! END DEFINITION; |
When using embedded SQL statements in step procedures, follow these guidelines:
Example 4-2 contains examples illustrating each of these guidelines.
For other high-level languages, the rules for beginning and ending SQL statements in step procedures vary. See the SQL documentation for more information about beginning and ending SQL statements in step procedures.
Before you can use SQL to access a database, you must declare the database. You do this in each server procedure that accesses the database. If you are using COBOL, name the Rdb database in the Working-Storage Section of the Data Division of your procedure using the DECLARE SCHEMA statement. This must appear in the procedure before you can use other SQL statements to reference data in the database.
Example 4-2 shows the DECLARE SCHEMA statement used in the procedure VR_COMPLETE_CHECKOUT_PROC to declare the database. (Example 4-7 contains the complete procedure.)
Example 4-2 Declaring the Database |
---|
************************************************************ DATA DIVISION. ************************************************************ WORKING-STORAGE SECTION. * * Return status to pass to ACMS * 01 RET-STAT PIC S9(9) COMP. 01 RSTAT PIC S9(9) COMP. . . . * * Declare the database schema. * EXEC SQL DECLARE EXTERNAL SCHEMA FILENAME AVERTZ_DATABASE:VEHICLE_RENTALS END-EXEC. |
When you use SQL with a distributed transaction, you must pass the transaction ID (TID) to SQL on each executable DML verb using an SQL context structure.
This section describes how to:
See Example 4-7 for a complete example of using precompiled SQL in a distributed transaction using COBOL. See the SQL documentation for information on how to define and use an SQL context structure.
Previous | Next | Contents | Index |