# Compaq ACMS for OpenVMS
Writing Applications

Previous | Contents | Index

### 2.3.5.4 Completing the Task Definition

As with the Review Car Rates task, the block step in the Review Reservation task uses DECforms to interface with the terminal user. Therefore, you need to assign the FORM I/O attribute to the block.

Although the Review Reservation task has just one processing step, that step can be repeated many times. You need to consider whether or not the task needs to have the same server process each time it runs that processing step; you decide to retain or release server context.

Suppose the REVIEW_RESERVATION_PROC procedure reads the first five records, and the form displays those records. For the user to look at the next five records, REVIEW_RESERVATION_PROC must keep a pointer in the file to keep track of which record was last read. You need some way to save this pointer so that the procedure can use it if the user wants to see more records.

You can choose one of two ways to retain pointers between steps in a task:

- Retain the pointers in a workspace
- Retain server context

To retain pointers in a workspace, the procedure must write those pointers to the workspace. Pointers are part of the context associated with a server process. Therefore, if you retain server context, you retain the file pointers and do not have to write those pointers to a workspace. However, in a task such as Review Reservation, retaining server context means retaining a process until the user looks at all the records the user wants to see.

The least expensive choice in terms of system resources is to write the file pointer to a workspace rather than retain server context. In the Review Reservation task, the procedure writes this file pointer to the WK_SAVE_NUMBER field of CO_RESERVE_WKSP and releases server context. Compaq ACMS for OpenVMS Concepts and Design Guidelines explains server context in more detail.

In addition to considering the general characteristics of the block step, consider the actions you want to take as a result of the work done in that block. Suppose that you want to take the same actions as those defined in the action part of the block step for the Review Car Rates task: repeat the task unless the user presses the PF4 key in the final exchange step. You use the REPEAT TASK clause in the action part of the block step definition.

    .
    .
    .
    END BLOCK WORK;

    ACTION
      REPEAT TASK;

Finally, use the WORKSPACE clause to name the workspaces that you define (CO_RESERVE_WKSP, QUIT_CTRL_WKSP, and MSG_WKSP) for the Review Reservation task. Example 2-7 shows the complete definition for the Review Reservation task.

Example 2-7 Complete Definition of Review Reservation Task

    REPLACE TASK REVIEW_RESERVATION_TASK /LIST=RVRSV.LIS
      WORKSPACES ARE CO_RESERVE_WKSP, QUIT_CTRL_WKSP, MSG_WKSP;

    BLOCK WORK WITH FORM I/O

      GET_COMPANY_ID:
      EXCHANGE
        TRANSCEIVE FROM RECORD CO_RESERVE_FORM_REC,
                               CO_RESERVE_FORM_REC_LIS
         SENDING CO_RESERVE_WKSP
         RECEIVING CO_RESERVE_WKSP, QUIT_CTRL_WKSP;
      ACTION IS
        CONTROL FIELD IS QUIT_CTRL_WKSP.QUIT_KEY
          "QUIT"     : EXIT TASK;
        END CONTROL FIELD;

      GET_FIVE_RESERVATIONS:
        PROCESSING
          CALL REVIEW_RESERVATION_PROC IN RESERVATION_SERVER
            USING CO_RESERVE_WKSP;
        ACTION IS
          IF (ACMS$STATUS_TYPE EQ "B")
          THEN GET ERROR MESSAGE;
               MOVE ACMS$T_STATUS_MESSAGE TO MSG_WKSP.MESSAGE_PANEL;
               GOTO NEXT EXCHANGE;
          ELSE GOTO STEP DISPLAY_RESERVATIONS;
          END IF;

      DISPLAY_ERROR:
       EXCHANGE
        TRANSCEIVE FORM RECORD MSG_FORM_REC, QUIT_CTRL_FORM_REC
         SENDING MSG_WKSP
         RECEIVING QUIT_CTRL_WKSP;
        ACTION
         IF (QUIT_CTRL_WKSP.QUIT_KEY EQ "QUIT")
         THEN EXIT TASK;
         ELSE GOTO STEP GET_COMPANY_ID;
         END IF;

      DISPLAY_RESERVATION:
      EXCHANGE
       TRANSCEIVE FORM RECORD CO_RESERVE_FORM_REC, QUIT_CTRL_FORM_REC
        SENDING CO_RESERVE_WKSP
        RECEIVING QUIT_CTRL_WKSP;
       ACTION IS
        CONTROL FIELD IS QUIT_CTRL_WKSP.QUIT_KEY
        "QUIT"   :   EXIT TASK;
        "MORE"   :   GOTO PREVIOUS PROCESSING;
        END CONTROL FIELD;

    END BLOCK WORK;
    ACTION
      REPEAT TASK;
    END DEFINITION;

# 2.4 Defining an Update Task

This section presents an update task, the Review Update task, that lets the terminal user review an existing reservation record and change information in the record. Table 2-4 describes the steps of an update task.

Table 2-4 Update Task
Step | Type
--- | ---
Display a panel to get information | Exchange step
Read information from a file | Processing step
Display an error message, if necessary | Exchange step
Display a panel with information | Exchange step
Update file and display message, if necessary | Nested Block step

The steps of an update task apply to the Review Update task in the following manner:

1. Display a panel requesting the name of the customer whose reservation record the terminal user wants to update.
2. Read information about the reservation from the Reservation file.
3. If an error occurs during the processing step, display the error message on the screen and return to the first step.
4. Display reservation review information, allowing the terminal user to update the data.
5. Check to see whether or not the user has changed the reservation record; if yes, write the new data to the Reservation file and display a message to the user.

## 2.4.1 Getting Information from the User

To get information from the terminal user, you display a panel. Here is the first exchange step of the Review Update task:

    GET_CUSTOMER_NAME:
      EXCHANGE
       TRANSCEIVE FORM RECORD RESERVE_FORM_REC, RESERVE_FORM_REC_LIS
        SENDING RESERVE_WKSP
        RECEIVING RESERVE_WKSP, QUIT_CTRL_WKSP;
      ACTION
        CONTROL FIELD IS QUIT_CTRL_WKSP.QUIT_KEY
        "QUIT"   :   EXIT TASK;
        END CONTROL FIELD;

This step is very similar to the first step in the inquiry task, Review Reservation. Both steps do the following:

- Call a form record to display a panel asking for a record key; in this case the record key is the customer's name.
- Let the terminal user end the task.
- Use an optional label to assign a name to the step.

As a result, the record definition for the workspace that you use to pass reservation data between the application and the form is very similar to the one in the Review Reservation task. Example 2-8 shows the record description of RESERVE_WKSP.

Example 2-8 Definition for RESERVE_WKSP Workspace

    Definition of record RESERVE_WKSP
    |   Contains field          CUST_NAME
    |   |  Datatype                 text size is 30 characters
    |   Contains field          CUST_STREET_ADDRESS
    |   |  Datatype                 text size is 30 characters
    |   Contains field          CUST_CITY
    |   |  Datatype                 text size is 20 characters
    |   Contains field          CUST_STATE
    |   |  Datatype                 text size is 2 characters
    |   Contains field          CUST_ZIP
    |   |  Datatype                 text size is 5 characters
    |   Contains field          CUST_PHONE
    |   |  Datatype                 text size is 10 characters
    |   Contains field          CAR_TYPE
    |   |  Datatype                 text size is 3 characters
    |   Contains field          RENTAL_DATE
    |   |  Datatype                 text size is 6 characters
    |   Contains field          RETURN_DATE
    |   |  Datatype                 text size is 6 characters

## 2.4.2 Retrieving Information from a File

As shown in the data entry and inquiry tasks, reading from or writing to a file requires a processing step. Here is the processing step for the Review Update task:

    FIND_RESERVATION:
      PROCESSING
       CALL FIND_RESERVE_PROC IN RESERVE_SERVER
        USING RESERVE_WKSP;
      ACTION
       IF (ACMS$T_STATUS_TYPE EQ "B")
       THEN GET ERROR MESSAGE;
            MOVE ACMS$T_STATUS_MESSAGE TO MSG_WKSP.MESSAGE_PANEL;
            GOTO NEXT EXCHANGE;
       ELSE GOTO STEP DISPLAY_RESERVATION;
       END IF;

When you update information, it is important that the contents of a record do not change from the time those contents are displayed to the user for update until the time you write the changed record back to the file. This is especially important in a multiuser application in which another user might update the record while it is being displayed on the terminal screen for the first user.

One way of ensuring the integrity of the record you are updating is to have the procedure lock the record and then retain server context between processing steps. However, it is much more efficient to release server context between processing steps. When you update a record, to ensure the integrity of the record without locking the record and retaining server context, you need to check whether the record was updated by someone else before writing the first user's changes to the file. See Compaq ACMS for OpenVMS Writing Server Procedures for further discussion on releasing server context.

As in the inquiry and data entry tasks, you must consider errors that can occur when the procedure tries to read from the file. If the reservation record for the customer name provided by the terminal user does not exist or is locked by another user, ACMS stores the value B in the ACMS$T_STATUS_TYPE field of the ACMS$PROCESSING_STATUS workspace. The processing step checks that field and, if the field contains B, retrieves the error message and stores it in the MSG_WKSP workspace. ACMS then passes control to the DISPLAY_ERROR exchange step:

    DISPLAY_ERROR:
      EXCHANGE
       TRANSCEIVE FORM RECORD MSG_FORM_REC, QUIT_CTRL_FORM_REC
        SENDING MSG_WKSP
        RECEIVING QUIT_CTRL_WKSP;
       ACTION
        IF (QUIT_CTRL_WKSP.QUIT_KEY EQ "QUIT")
        THEN EXIT TASK;
        ELSE GOTO STEP GET_CUSTOMER_NAME;
        END IF;

This exchange step sends the error message stored in MSG_WKSP to the MSG_FORM_REC form record for display to the terminal screen. The action part of this step tests the QUIT_KEY field of the QUIT_CTRL_WKSP workspace to see whether or not the terminal user wants to exit from the task. If the user presses the PF4 key, DECforms returns the value "QUIT" to the workspace, and ACMS ends the task and returns the user to the menu. Otherwise, ACMS passes control to the first step in the task definition.

## 2.4.3 Letting the User Update the Information

Once a procedure has read information from a file, you can display that information to the terminal user. The user can then supply information, in the form of changes, to be written back to the file. You use an exchange step to call a form record to display information to the user and to accept changes.

Here is the exchange step that displays information for the Review Update task:

    DISPLAY_RESERVATION:
      EXCHANGE
       TRANSCEIVE FORM RECORD RESERVE_FORM_REC, RESERVE_FORM_REC_LIS
        SENDING RESERVE_WKSP
        RECEIVING RESERVE_WKSP, QUIT_CTRL_WKSP
                  SHADOW IS RESERVE_SHADOW_WKSP;
      ACTION
       CONTROL FIELD IS QUIT_CTRL_WKSP.QUIT_KEY
       "QUIT"  :  EXIT TASK;
       END CONTROL FIELD;

For an inquiry task, such as Review Reservation, this second exchange step is the final step in the task. However, in an update task, the user can make changes to the information displayed.

The DISPLAY_RESERVATION step uses RESERVE_WKSP to send the information read by the FIND_RESERVE_PROC procedure to the form for display. The step also uses RESERVE_WKSP to store the information that the terminal user returns.

Unlike exchange steps in the data entry and inquiry tasks, this step uses a shadow workspace to determine whether or not the terminal user changed any information in the reservation record. When you declare a shadow workspace, DECforms returns a value to that workspace that indicates whether or not the user changed any data in the record. In this exchange step, RESERVE_SHADOW_WKSP is the shadow workspace for the RESERVE_WKSP workspace.

The record description for RESERVE_SHADOW_WKSP is the same as for RESERVE_WKSP, except that you must add a field to store the value that DECforms returns. Example 2-9 shows the definition.

Example 2-9 Record Description for RESERVE_SHADOW_WKSP Workspace

    Definition of record RESERVE_SHADOW_WKSP
    |   Contains field          REC_STATUS
    |   |  Datatype                 text size is 1 character
    |   Contains field          CUST_NAME_SHADOW
    |   |  Datatype                 text size is 1 character
    |   Contains field          CUST_STREET_ADDRESS_SHADOW
    |   |  Datatype                 text size is 1 character
    |   Contains field          CUST_CITY_SHADOW
    |   |  Datatype                 text size is 1 character
    |   Contains field          CUST_STATE_SHADOW
    |   |  Datatype                 text size is 1 character
    |   Contains field          CUST_ZIP_SHADOW
    |   |  Datatype                 text size is 1 character
    |   Contains field          CUST_PHONE_SHADOW
    |   |  Datatype                 text size is 1 character
    |   Contains field          CAR_TYPE_SHADOW
    |   |  Datatype                 text size is 1 character
    |   Contains field          RENTAL_DATE_SHADOW
    |   |  Datatype                 text size is 1 character
    |   Contains field          RETURN_DATE_SHADOW
    |   |  Datatype                 text size is 1 character

If the terminal user changed any data in RESERVE_WKSP, ACMS stores a 1 in the REC_STATUS field of RESERVE_SHADOW_WKSP when the transceive operation completes. The status field in the shadow workspace must be the first field in your record definition. In your DECforms IFDL code, you must assign the TRACKED attribute to the fields of shadow workspaces. See the DECforms documentation for information on using this attribute.

After the DISPLAY_RESERVATION step ends, you need to check the shadow workspace to see whether or not the reservation record has changed. If it has, write the new record to the Reservation file and display a message on the terminal screen confirming the update.

## 2.4.4 Writing the New Information to the File

The CHECK_RESERVE_CHANGES step is a nested block step that includes the following parts:

- Block conditional clause
- Processing step
- Exchange step

By using a nested block step, you can group processing and exchange steps and have ACMS process them only if a certain condition is met. You introduce a nested block the same way you introduce a block, with the BLOCK WORK keywords. As with other steps, you can assign a label to a nested block and refer to it from elsewhere in the task definition.

A block conditional clause is one of the four ADU conditional clauses (CONTROL FIELD, IF THEN ELSE, SELECT FIRST, or WHILE DO) used at the block step level. You can use it to start an exchange step, a processing step, or another block step. However, you can use a block conditional clause only at the start of a block step. You cannot use it between steps within the block. Here is the definition for the CHECK_RESERVE_CHANGES nested block step:

    CHECK_RESERVE_CHANGES:
      BLOCK WORK
       IF (RESERVE_SHADOW_WKSP.REC_STATUS EQ "1")
       THEN
         PROCESSING
          CALL WRITE_RESERVE_PROC IN RESERVE_SERVER
           USING RESERVE_WKSP;
         ACTION
          MOVE "RESERVATION RECORD UPDATED" TO MSG_WKSP.MESSAGE_PANEL;

         EXCHANGE
          SEND FORM RECORD MSG_FORM_REC
           SENDING MSG_WKSP;
       END IF;
      END BLOCK;

In the CHECK_RESERVE_CHANGES step, an IF THEN ELSE block conditional clause tests the shadow workspace. If the REC_STATUS field equals 1, ACMS processes the processing and exchange steps that follow the THEN keyword. The processing step calls the WRITE_RESERVE_PROC procedure, which writes the new reservation record to the Reservation file.

The action part of the processing step moves the message "RESERVATION RECORD UPDATED" to the MSG_WKSP workspace, and the exchange step then sends that message to DECforms for display.

If the shadow record indicates that the terminal user did not change any data in the reservation record, ACMS does not perform the processing and exchange steps in the CHECK_RESERVE_CHANGES block step. Note that you do not need to include the ELSE keyword in the IF THEN ELSE clause. ACMS passes control to the clause following the END IF keywords. Be sure to end the nested block with the END BLOCK keywords.

## 2.4.5 Completing the Task Definition

The Review Update task uses DECforms to interface with the terminal; therefore, you need to assign the FORM I/O attribute to the block. Nested blocks inherit the attributes that you assign to their parent blocks; so, you do not need to include the FORM I/O keywords with the CHECK_RESERVE_CHANGES step.

Because you want to repeat this task automatically rather than make the terminal user choose the task again from the menu, include the REPEAT TASK clause in the action part of the parent block.

Finally, you must name the workspaces used by the steps in the task. In the Review Update task these are RESERVE_WKSP, RESERVE_SHADOW_WKSP, QUIT_CTRL_WKSP, and MSG_WKSP. Declare these workspaces using the WORKSPACES ARE clause in the task definition.

    WORKSPACES ARE RESERVE_WKSP, RESERVE_SHADOW_WKSP, QUIT_CTRL_WKSP, MSG_WKSP;

Example 2-10 shows the complete definition for the Review Update task.

Example 2-10 Complete Definition of Review Update Task

    REPLACE TASK REVIEW_UPDATE_TASK /LIST=RVSCHED.LIS
      WORKSPACES ARE RESERVE_WKSP, QUIT_CTRL_WKSP, MSG_WKSP,
                     RESERVE_SHADOW_WKSP;

    BLOCK WORK WITH FORM I/O

    GET_CUSTOMER_NAME:
      EXCHANGE
       TRANSCEIVE FORM RECORD RESERVE_FORM_REC, RESERVE_FORM_REC_LIS
        SENDING RESERVE_WKSP
        RECEIVING RESERVE_WKSP, QUIT_CTRL_WKSP;
      ACTION
        CONTROL FIELD IS QUIT_CTRL_WKSP.QUIT_KEY
        "QUIT"   :   EXIT TASK;
        END CONTROL FIELD;

    FIND_RESERVATION:
      PROCESSING
       CALL FIND_RESERVE_PROC IN RESERVE_SERVER
        USING RESERVE_WKSP;
      ACTION
       IF (ACMS$T_STATUS_TYPE EQ "B")
       THEN GET ERROR MESSAGE;
            MOVE ACMS$T_STATUS_MESSAGE TO MSG_WKSP.MESSAGE_PANEL;
            GOTO NEXT EXCHANGE;
       ELSE GOTO STEP DISPLAY_RESERVATION;
       END IF;

    DISPLAY_ERROR:
      EXCHANGE
       TRANSCEIVE FORM RECORD MSG_FORM_REC, QUIT_CTRL_FORM_REC
        SENDING MSG_WKSP
        RECEIVING QUIT_CTRL_WKSP;
       ACTION
        IF (QUIT_CTRL_WKSP.QUIT_KEY EQ "QUIT")
        THEN EXIT TASK;
        ELSE GOTO STEP GET_CUSTOMER_NAME;
        END IF;

    DISPLAY_RESERVATION:
      EXCHANGE
       TRANSCEIVE FORM RECORD RESERVE_FORM_REC, RESERVE_FORM_REC_LIS
        SENDING RESERVE_WKSP
        RECEIVING RESERVE_WKSP, QUIT_CTRL_WKSP
                  SHADOW IS RESERVE_SHADOW_WKSP;
      ACTION
       CONTROL FIELD IS QUIT_CTRL_WKSP.QUIT_KEY
       "QUIT"  :  EXIT TASK;
       END CONTROL FIELD;

    CHECK_RESERVE_CHANGES:
      BLOCK WORK
       IF (RESERVE_SHADOW_WKSP.REC_STATUS EQ "1")
       THEN
         PROCESSING
          CALL WRITE_RESERVE_PROC IN RESERVE_SERVER
           USING RESERVE_WKSP;
         ACTION
          MOVE "RESERVATION RECORD UPDATED" TO MSG_WKSP.MESSAGE_PANEL;

         EXCHANGE
          SEND FORM RECORD MSG_FORM_REC
           SENDING MSG_WKSP;
       END IF;
      END BLOCK;
    END BLOCK;
    ACTION
      REPEAT TASK;
    END DEFINITION;

Previous | Next | Contents | Index