# Compaq ACMS for OpenVMS
Writing Applications

Previous | Contents | Index

### 9.6.2.4 Setting the Retry Time for Failed Tasks

You use the ACMSGEN parameter QTI_RETRY_TIMER to determine how long the QTI process waits before it retries a task that it has already dequeued, but that did not complete successfully and that can be retried. For example, if the QTI process dequeues a task for an application that is not started, the QTI process waits for the number of seconds identified by the QTI_RETRY_TIMER parameter before retrying the task.

### 9.6.2.5 Setting the Polling Time for Task Queues

You use the ACMSGEN parameter QTI_POLLING_TIMER to specify the amount of time that the QTI process waits to poll populated queues that previously had an RMS lock outstanding.

## 9.6.3 Auditing Done by the QTI Process

The QTI audits all ACMS operator commands that start, stop, or set queues. In addition, the QTI audits all task invocations that fail. The audit trail record of failed task invocations shows the following:

- The error that caused the task invocation to fail
- What the QTI has done with the queued task element

Example 9-1 shows a sample QTI audit entry.

Compaq ACMS for OpenVMS Managing Applications provides more information on application auditing with the ACMS Audit Trail Report Utility.

Example 9-1 Sample QTI Audit Entry

    ************************************************************
    Type   : COMMAND   Time   : 24-NOV-1987 16:50:28.38
    User   : OPERATOR
    Text   : Successful start for queue PAYROLL_QUEUE
    ************************************************************
    Type   : ERROR     Time   : 24-NOV-1987 16:52:04.62
    Queue  : PAYROLL_QUEUE
    ErrQue : PAYROLL_ERROR_QUEUE
    Elem Id: MYNODE::28000114-00000003-87A9ECE0-0090A5F7
    Appl   : PAYROLL
    Task   : HIRE_EMPLOYEE
    User   : JONES
    Text   : Error processing queued task
    -ACMSQUE-E-ERRGETPROC, Error returned from ACMS$GET_PROCEDURE_INFO
    -ACMS-E-NOSUCH_PKG, There is no such package defined
    -ACMSQUE-I-QTRETRY, Queued task will be retried later
    ************************************************************

## 9.6.4 How the QTI Handles Errors

Once the QTI has submitted a task to an ACMS application, it must handle any errors that result when the task is processed. The QTI handles errors in one of four ways:

1. Retries the task. Table 9-2 lists the errors that result in this action.

   Table 9-2 Errors That Result in Queued Task Retry
   Error | QTI assumes that...
   --- | ---
   ACMS$_APPL_NOT_STARTED | The application is not started.
   ACMS$_CALL_CANCELLED | The task was canceled, perhaps due to a system or application shutdown.
   ACMS$_INVPROCID | The application stopped unexpectedly.
   ACMS$_MAX_TASKS | There is a temporary resource limitation.
   ACMS$_NOSUCH_PKG | The application is not started.
   ACMS$_QTI_RETRY | The task returns this value as the task completion status, thereby directing the QTI to retry this queued task later.
   ACMS$_SRVDEAD | The server stopped unexpectedly.
   ACMS$_TASK_DISABLED | The task will be enabled later.
   ACMS$_WSPALLOCERR | There is a temporary resource limitation.
   ACMS$_WSPLOCKED | There is a temporary resource limitation.

2. Does not retry the task, deletes the queued task element from the task queue and writes it to the error queue, if any. Table 9-3 lists the errors that result in this action.

   Table 9-3 Errors That Result in Writing Queued Task Elements to an Error Queue
   Error | Cause of Error
   --- | ---
   ACMS$_BADUSER | QTI was unable to sign in the user name.
   ACMS$_CANTRETRY | The submitter services have tried to connect to server services twice, using different protocols, without success.
   ACMS$_ERRREADARG | There is a problem with the workspaces being used.
   ACMS$_INVQUEELM | Invalid queue element; assume the queue is corrupt.
   ACMS$_NOSUCH_PROC | The task does not exist in the application.
   ACMS$_NOTRANSADB | The task definition has been modified to participate in a distributed transaction, but the application database (ADB) has not been rebuilt.
   ACMS$_NOTRANSNODE | The application node is not running ACMS Version 3.2 or later.
   ACMS$_QTI_NORETRY | The task has returned this value as the task completion status, thereby directing the QTI not to retry this queued task.
   ACMS$_SECURITY_CHECK_FAILED | The user name is not allowed access in the task ACL.
   ACMS$_TASKARGWSPERR | The number or size of workspaces supplied to the task is incorrect.
   ACMS$_TASKNOTCOMP | The task is not composable.
   QUE$_INVIOMETH | The task being selected uses terminal, stream, or request (TDMS) I/O.

3. Retries the task once. If the same error occurs twice consecutively, then the QTI does not retry the task. Instead, it deletes it from the task queue and writes it to the error queue, if any. Any error not shown in Table 9_2 or Table 9-3 can cause this action.
4. Immediately retries the task up to five times. If one of the errors is still returned after five retries, the QTI handles the error according to the third way listed above. Table 9-4 lists the errors that result in this action.

Table 9-4 Errors That Result in Immediate Retry of Queued Task
Error | Cause of Error
--- | ---
ACMS$_QTI_RETRY_IMMEDIATELY | The task has returned this value as the completion status, thereby directing the QTI to retry the queued task immediately.
ACMS$_TRANSTIMEDOUT | The distributed transaction did not complete with the time limit specified in the application definition.

See Section 9.7 for information about how to process elements from an error queue.

If a task invocation does not complete successfully, the QTI writes an audit record to the ACMS audit trail log. The audit record indicates the reason for the task invocation failure as well as what the QTI did with the queued task element (to be retried later, moved to the error queue, or deleted from the task queue).

Note There are three error messages, ACMS$_QTI_RETRY, ACMS$_QTI_RETRY_IMMEDIATELY, and ACMS$_QTI_NORETRY, that a queued task can return that explicitly direct whether or not the QTI retries the queued task.

# 9.7 Processing Error Queues

You process elements from an error queue in the same way that you can process elements from any ACMS task queue; you use the ACMS$DEQUEUE_TASK service.

Application programs can access queue files to queue and dequeue task elements using the ACMS queuing services. The queue or dequeue operation can be atomic with other operations by including them in a distributed transaction.

For example, a task definition includes the following operations within a distributed transaction:

- Use the ACMS$DEQUEUE_TASK service to dequeue queued task elements from an error queue.
- Correct the field that caused the task invocation to fail (which presumably is why the queued task element is on the error queue).
- Write a statistical record to an RMS file.
- Use the ACMS$QUEUE_TASK service to queue the queued task element back to a task queue. The QTI can then retry the queued task element.

By performing the operations in this example within a distributed transaction, ACMS ensures that all operations occur or none of the operations occur. For example, if a system failure occurs after dequeuing the task and writing the statistics record but before enqueuing the task, then ACMS rolls back the dequeue operation and the write operation to the state they were in before the operation began.

Example 9-2 shows a task that can be selected by a terminal user to dequeue a queued task element from an error queue, correct the element, and queue the corrected element to another task queue.

Example 9-2 A Task That Dequeues from an Error Queue

    !
    !   CORR_QTE_ERR.TDF This task calls a program to read queued task
    !   element entries from the error queue PAY_ERR_QUE.
    !   The entry will be displayed to a terminal operator.
    !   The operator will either correct the entry and
    !   resubmit the task to the PAY_QUE, or delete
    !   the entry without further processing.

    !
    SET LOG CORR_QTE_ERR.TDF_LOG
    REPLACE TASK CORR_QTE_ERR
    DEFAULT SERVER IS QUE_EXAM_SERVER;
    WORKSPACES ARE QTE_INFO, EMP_PAY_REC, QUE_MISC, CONT_PROC;

    BLOCK WORK WITH REQUEST I/O
    !
    !  Start a distributed transaction, then call procedure to read the next
    !  entry in the error queue PAY_ERR_QUE. QTE_INFO contains the queued
    !  task element structure, and EMP_PAY_REC is the data record associated
    !  with the task.
    !
    GET_ENTRY:

    BLOCK WORK WITH DISTRIBUTED TRANSACTION

        PROCESSING
         CALL GET_QTE_ERRENT USING QTE_INFO,
              EMP_PAY_REC;
    !
    !  If the procedure call fails, roll back the transaction and cancel the
    !  task.  If not, use GET ERROR MESSAGE to translate this QTE's error
    !  status and display that text on the form.
    !
        CONTROL FIELD ACMS$T_STATUS_TYPE
        "B" : ROLLBACK TRANSACTION;
              CANCEL TASK;
        "G" : GET ERROR MESSAGE NUMBER QTE_LAST_ERR_SYM INTO QTE_LAST_ERR;
        END CONTROL FIELD;

    DISPLAY_ENTRY:
        EXCHANGE
         REQUEST IS DISP_QTE_ERRENT USING QTE_INFO, QUE_MISC;
    !
    !  REQU will cause the entry to be queued back onto the PAY_QUE queue
    !  for processing.  DELE will cause the removal of the entry from the
    !  error queue to be committed.  QUE_MISC contains the PROGRAM_REQUEST_KEY.
    !
        CONTROL FIELD IS PROGRAM_REQUEST_KEY
          "REQU"   : GOTO STEP REQUE_ENTRY;
          "DELE"   : EXIT BLOCK;
          NOMATCH  : ROLLBACK TRANSACTION;
                     CANCEL TASK;
        END CONTROL FIELD;
    REQUE_ENTRY:
        PROCESSING
          CALL REQUE_QTE_ERRENT USING QTE_INFO;

        CONTROL FIELD ACMS$T_STATUS_TYPE
        "B"      : ROLLBACK TRANSACTION;
                   CANCEL TASK;
        "G"      : EXIT BLOCK;
        NOMATCH  : ROLLBACK TRANSACTION;
                   CANCEL TASK;
        END CONTROL FIELD;

    END BLOCK;

    ACTION IS
      COMMIT TRANSACTION;

    CHECK_CONTINUE:

        EXCHANGE
         READ CONT_PROC WITH PROMPT
         "Enter Y to continue, N to EXIT TASK==> ";

        ACTION
         CONTROL FIELD IS CONT_PROC.CONT_PROC_CHECK
         "Y"      : REPEAT TASK;
         "N"      : EXIT TASK;
         NOMATCH  : CANCEL TASK;
         END CONTROL FIELD;

    END BLOCK WORK;
    END DEFINITION;

By starting a distributed transaction on the nested block step, the CORR_QTE_ERR task ensures that the GET_ENTRY, DISPLAY_ENTRY, and REQUE_ENTRY steps complete successfully or are rolled back.

Be sure that you enable journaling for both the queue file from which you are dequeuing elements and the queue file to which you are enqueuing elements. Use the DCL command SET FILE/RU_JOURNALING to enable journaling on those files.

Example 9-3 shows the GET_QTE_ERRENT procedure called in the first processing step of the task shown in Example 9_2. Example 9-4 shows the REQUE_QTE_ERRENT procedure that is called in the second processing step of that task.

Example 9-3 A Dequeue Procedure

    IDENTIFICATION DIVISION.
    **************************************************************
    *                                                            *
    PROGRAM-ID. GET_QTE_ERRENT.
    *                                                            *
    *                                                            *
    *               Version:        01                           *
    *               Edit date:      06-APR-1988                  *
    *                                                            *
    **************************************************************
    **************************************************************
    *         P R O G R A M    D E S C R I P T I O N             *
    *                                                            *
    * GET_QTE_ERRENT is called from task CORR_QTE_ERR.  This     *
    *  ACMS procedure calls ACMS$DEQUEUE_TASK to dequeue a       *
    *  queued task element (QTE) from the error queue            *
    *  PAY_ERR_QUEUE.                                            *
    *                                                            *
    * INPUT:  QTE_INFO, a record containing the queue task       *
    *         element fields, queue name and queued task         *
    *         element information.                               *
    *  EMP_PAY_REC, the employee record needed for               *
    *   the task.                                                *
    *                                                            *
    * OUTPUT: The queued task element information returned       *
    *   in QTE_INFO and the data returned to EMP_PAY_REC         *
    *         from ACMS$DEQUEUE_TASK call.                       *
    *                                                            *
    *                                                            *
    **************************************************************
    *                                                            *
    *                                                            *
    *                   C O P Y R I G H T                        *
    *                                                            *
    *   (C) Copyright 1988                                       *
    *   Digital Equipment Corporation, Maynard Massachusetts     *
    *                                                            *
    *   DIGITAL assumes no responsibility for the use or relia-  *
    *   bility of its software on equipment that is not sup-     *
    *   plied by DIGITAL.                                        *
    **************************************************************
    ENVIRONMENT DIVISION.
    CONFIGURATION SECTION.
    SOURCE-COMPUTER.        VAX-11.
    OBJECT-COMPUTER.        VAX-11.
    **************************************************************
    DATA DIVISION.
    **************************************************************
    *                                                            *
    *          C O M M O N   D E C L A R A T I O N S             *
    *                                                            *
    **************************************************************
    WORKING-STORAGE SECTION.
    *
    * Set up fields to receive element id from ACMS$DEQUEUE_TASK.
    *
    01 RET-QTE-ID.
       03  PIP   PIC S9(9) COMP.
       03  SEQ-NO   PIC S9(9) COMP.
       03  ADT1   PIC S9(9) COMP.
       03  ADT2   PIC S9(9) COMP.
       03  NODE-NAME-LEN  PIC X.
       03  NODE-NAME  PIC X(15) VALUE ''.

    *
    01 STATUS-RESULT   PIC S9(9) COMP.

    * Set up a descriptor list with number of workspaces this task
    *  requires and pointers to each individual workspace descriptor.
    *  The USAGE IS POINTER allows us to define the address at runtime.
    *
    01 WS_DESC_LIST.
       05 DESC_LIST_CNT             PIC S9(9) COMP VALUE 1.
       05 QTE_WS_DESC_PTR           USAGE IS POINTER.
    *
    * Set up a descriptor for each workspace being passed with the
    *  workspace size and a pointer to the address of the record,
    *  also to be defined at runtime.
    *
    01 QTE_WS_DESC.
       05 EMP_PAY_REC_SIZE          PIC S9(9) COMP VALUE IS 13.
       05 EMP_PAY_REC_PTR           USAGE IS POINTER.
    **************************************************************
    LINKAGE SECTION.
    COPY "QTE_INFO" FROM DICTIONARY.
    COPY "EMP_PAY_REC" FROM DICTIONARY.
    ***************************************************************
    PROCEDURE DIVISION USING QTE_INFO,
        EMP_PAY_REC
                GIVING STATUS-RESULT.
    ***************************************************************
    MAIN-PROCEDURE.
    *
    * Set up addresses for the pointers to reference.
    *
     SET QTE_WS_DESC_PTR TO REFERENCE OF QTE_WS_DESC.
     SET EMP_PAY_REC_PTR TO REFERENCE OF EMP_PAY_REC.
    *
    * Enable the flag to say we do not want to wait if the queue is
    *  empty.
    *
     MOVE 2 TO FLAG.

    CALL-DEQUE.

            CALL "ACMS$DEQUEUE_TASK" USING BY DESCRIPTOR PAY_ERR_QUE,
                                                         OMITTED,
                                           BY REFERENCE  FLAG,
                                           BY DESCRIPTOR RET_TASK,
                                           BY DESCRIPTOR RET_APPL,
                                           BY REFERENCE WS_DESC_LIST,
                                           BY REFERENCE RET_WKSP_CNT,
                                           BY REFERENCE QTE_PRIO,
                                           BY DESCRIPTOR QTE_SUBMITTER,
                                           BY REFERENCE RET-QTE-ID,
                                           BY REFERENCE QTE_ERR_CNT,
                BY REFERENCE QTE_LAST_ERR_SYM,
                BY REFERENCE QTE_ERR_ADT
         GIVING STATUS-RESULT.
    *
    * Move information into EMP_PAY_REC returned by the call to the QTE_INFO
    * workspace, as it will be used by the request to display both record
    * data and QTE information.
    *

     MOVE BADGE OF EMP_PAY_REC TO BADGE OF QTE_INFO.
     MOVE PAYCODE OF EMP_PAY_REC TO PAYCODE OF QTE_INFO.
     MOVE HOURS OF EMP_PAY_REC TO HOURS OF QTE_INFO.
     MOVE WAGE OF EMP_PAY_REC TO WAGE OF QTE_INFO.
     MOVE VACATION OF EMP_PAY_REC TO VACATION OF QTE_INFO.
     MOVE SPACES TO QTE_SUBMITTER OF QTE_INFO.
    *
    * Move PID into displayable field to be returned to the request.
    *
    SPACE-MOVE.

     MOVE NODE-NAME TO QTE_NODE.
     MOVE PID TO QTE_PID.

    EXIT-GET-QTE-ERRENT.

     EXIT PROGRAM.

Example 9-4 An Enqueue Procedure

    IDENTIFICATION DIVISION.
    ***************************************************************************
    *                                                                         *
    PROGRAM-ID. REQUE_QTE_ERRENT.
    *                                                                         *
    *               Version:        01                                        *
    *               Edit date:      06-APR-1988                               *
    *                                                                         *
    ***************************************************************************
    ***************************************************************************
    *         P R O G R A M    D E S C R I P T I O N                          *
    *                                                                         *
    * REQUE_QTE_ERRENT is called from task CORR_QTE_ERR.  This ACMS procedure *
    * calls ACMS$QUEUE_TASK to requeue a queued task element (QTE) entry from *
    * the PAY_ERR_QUE.  The QTE is requeued to the PAY_QUE queue.             *
    *                                                                         *
    * INPUT:  QTE_INFO, a record containing the task element information      *
    *         to be queued.                                                   *
    *   EMP_PAY_REC, a record contains the user data needed by the task.      *
    *                                                                         *
    ***************************************************************************
    *                                                                         *
    *                                                                         *
    *                   C O P Y R I G H T                                     *
    *                                                                         *
    *   (C) Copyright 1988                                                    *
    *   Digital Equipment Corporation, Maynard Massachusetts                  *
    *                                                                         *
    *   DIGITAL assumes no responsibility for the use or reliability of its   *
    *   software on equipment that is not supplied by DIGITAL.                *
    ***************************************************************************
    ENVIRONMENT DIVISION.
    CONFIGURATION SECTION.
    SOURCE-COMPUTER.        VAX-11.
    OBJECT-COMPUTER.        VAX-11.
    ***************************************************************************
    DATA DIVISION.
    ***************************************************************************
    *                                                                         *
    *          C O M M O N   D E C L A R A T I O N S                          *
    *                                                                         *
    ***************************************************************************
    WORKING-STORAGE SECTION.
    *
    01 STATUS-RESULT   PIC 9(9) COMP VALUE IS 0.
    *
    * Copy in record this task needs to run.
    *
    COPY "EMP_PAY_REC" FROM DICTIONARY.
    *
    * Set up descriptor list with number of workspaces we are passing
    *  and pointers to each individual workspace descriptor.
    *
    01 WS_DESC_LIST.
       05 DESC_LIST_CNT  PIC S9(9) COMP VALUE 1.
       05 QTE_WS_DESC_PTR  POINTER VALUE IS REFERENCE QTE_WS_DESC.

    01 QTE_WS_DESC.
       05 EMP_PAY_REC_SIZE  PIC S9(9) COMP VALUE IS 13.
       05 EMP_PAY_REC_PTR  POINTER VALUE IS REFERENCE EMP_PAY_REC.

    **************************************************************
    LINKAGE SECTION.
    COPY "QTE_INFO" FROM DICTIONARY.
    ***************************************************************
    PROCEDURE DIVISION USING QTE_INFO
                GIVING STATUS-RESULT.
    ***************************************************************
    MAIN-PROCEDURE.
    *
    * Move data received from the call to ACMS$DEQUEUE_TASK, and
    *  passed to the operator, back to EMP_PAY-REC.
    *
     MOVE BADGE IN QTE_INFO TO BADGE IN EMP_PAY_REC.
     MOVE PAYCODE IN QTE_INFO TO PAYCODE IN EMP_PAY_REC.
     MOVE WAGE IN QTE_INFO TO WAGE IN EMP_PAY_REC.
     MOVE VACATION IN QTE_INFO TO VACATION IN EMP_PAY_REC.

    CALL-QUEUE.

     CALL "ACMS$QUEUE_TASK" USING BY DESCRIPTOR PAY_QUE,
             BY DESCRIPTOR RET_TASK,
             BY DESCRIPTOR RET_APPL,
             BY REFERENCE WS_DESC_LIST,
             BY REFERENCE FLAG,
             BY REFERENCE QTE_PRIO
        GIVING STATUS-RESULT.

    EXIT-REQUE-QTE-ERRENT.

     EXIT PROGRAM.

Previous | Next | Contents | Index