Compaq ACMS for OpenVMS
Systems Interface Programming


Previous Contents Index

7.5 Pascal Agent Program that Uses ACMS$WAIT

This Pascal agent program signs in to ACMS, gathers transactions from various nodes, and generates a report after all transactions are complete. It shows the use of ACMS$WAIT.

Example 7-5 Pascal Agent Program that Uses ACMS$WAIT

[INHERIT('SYS$LIBRARY:STARLET','SYS$LIBRARY:ACMSPAS')] 
PROGRAM campus_transactions(INPUT,OUTPUT); 
 
{ Program to gather transactions from various nodes. 
  After all transactions are complete, generate a report } 
  
CONST 
  pstring_length = 32; 
 
  
TYPE 
 
  uword = [WORD] 0..65535;                    { Unsigned word } 
  ubyte = [BYTE] 0..255;                      { Unsigned byte } 
 
  pstring = PACKED ARRAY [1..pstring_length] OF CHAR; 
 
  { descriptor datatype } 
  desc_type = [BYTE(8)] 
              RECORD 
              length : [POS(0)] uword; 
              dtype  : [POS(16)] ubyte; 
              class  : [POS(24)] ubyte; 
              ptr    : [POS(32),UNSAFE] INTEGER; 
              END; 
  
  quad = PACKED ARRAY [0..1] OF [UNSAFE] INTEGER; 
 
  
  nodes = (eku,nku,wku,ul,cmu); 
 
  arg_list = PACKED ARRAY [0..3] OF [UNSAFE] INTEGER; 
    
VAR 
  submitter_id : ACMS$SUBMITTER_ID; 
  exchange_io_id: ACMS$EXCHANGE_IO_ID; 
  status       : [unsafe] INTEGER; 
  status_block : ARRAY[eku..cmu] OF quad; 
  selection_string : ARRAY[eku..cmu] of desc_type; 
  padded_application_name : pstring; 
  padded_task_name : pstring; 
  status_string    : ARRAY[eku..cmu] of desc_type; 
  argument_list: ARRAY[eku..cmu] OF arg_list; 
  i : nodes; 
 
  
{ Run-time library output routine } 
[external] FUNCTION lib$put_output(%REF desc :desc_type):integer;extern; 
 
{ Run-time library routine to signal errors } 
[ASYNCHRONOUS,EXTERNAL(LIB$SIGNAL)] 
PROCEDURE signal(%IMMED condition : INTEGER; 
                 %IMMED fao_parms : [UNSAFE,LIST] INTEGER);EXTERN; 
 
FUNCTION init_dyndesc:desc_type; 
{ Function to initialize dynamic string desciptors } 
VAR 
 temp : desc_type; 
 
 
BEGIN 
   WITH temp DO 
   BEGIN 
     length := 0; 
     class := dsc$k_class_d; 
     dtype := dsc$k_dtype_t; 
     ptr := 0; 
   END; 
   init_dyndesc := temp; 
END ; { function init_dyndesc} 
 
 
PROCEDURE call_task( SUBMITTER_ID :ACMS$SUBMITTER_ID; 
                     APPLICATION_NAME : pstring; 
                     TASK_NAME : pstring; 
                     VAR argument_list: arg_list; 
                     VAR STATUS_BLOCK : quad); 
 
 
{ Procedure to perform an $acms$_call_a for the requested task } 
 
TYPE 
  uword = [WORD] 0..65535; 
 
  item_type = [BYTE (12)] 
              RECORD 
                buffer_length : [POS (0)] uword; 
                item_code     : [POS (16)] uword; 
                buffer_address: [POS (32),UNSAFE] INTEGER; 
                ret_length_adr: [POS (64),UNSAFE] INTEGER; 
              END ; {item_type} 
 
 
   list_type = [BYTE (16)] 
               RECORD 
                  list : [POS (0) ] item_type; 
                  term : [POS (96)] INTEGER; 
               END; {list_type} 
 VAR 
   status    : [UNSAFE] INTEGER; 
   proc_list : list_type; 
   procedure_id : ACMS$PROCEDURE_ID; 
   ACMS$EFN  : [EXTERNAL] ubyte; 
 
 
 BEGIN { call_task} 
 
   { Build get procedure info list } 
   WITH proc_list.list DO 
     BEGIN 
       buffer_length := acms$s_procedure_id; 
       item_code := acms$k_proc_procedure_id; 
       buffer_address := iaddress(procedure_id); 
       ret_length_adr := 0; 
     END ; {with proc_list} 
   proc_list.term := 0; 
 
   { Get procedure_id via acms$get_procedure_info } 
   status := $ACMS$GET_PROCEDURE_INFO(SUBMITTER_ID := submitter_id, 
                                     PACKAGE := application_name, 
                                     procedure_ := task_name, 
                                     item_list := proc_list); 
   IF not odd(status) THEN SIGNAL(status); 
 
      
   status := $ACMS$CALL_A(SUBMITTER_ID := submitter_id, 
                          PROCEDURE_ID := procedure_id, 
                          ARGUMENTS := argument_list, 
                          EFN := ACMS$EFN, 
                          COMP_STATUS := status_block); 
   IF not odd(status) THEN SIGNAL(status); 
 
 END ; { procedure call_task } 
   
 
 
BEGIN { main } 
 
  { Init argument list for calls } 
  FOR i := eku TO cmu DO 
  BEGIN 
    status_string[i] := init_dyndesc; 
    selection_string[i] := init_dyndesc; 
    
    argument_list[i][0] := 3; {Number of argument in list} 
    argument_list[i][1] := IADDRESS(selection_string[i]); 
    argument_list[i][2] := IADDRESS(status_string[i]); 
    argument_list[i][3] := IADDRESS(exchange_io_id); 
  END;{for} 
 
  { sign into acms } 
  
  status := $ACMS$SIGN_IN(SUBMITTER_ID := submitter_id); 
  IF not odd(status) THEN SIGNAL(status); 
 
  status := $ACMS$INIT_EXCHANGE_IO(SUBMITTER_ID := submitter_id, 
                                   EXCHANGE_IO_ID := exchange_io_id ); 
  IF not odd(status) THEN SIGNAL(status); 
    
  padded_task_name := PAD ( 'ENROLLMENT_TRANSACTIONS', ' ', pstring_length ); 
    
  padded_application_name := PAD ( 'EKU::TRANSACTIONS', ' ', pstring_length ); 
 
  
  call_task(SUBMITTER_ID := submitter_id, 
            application_name := padded_application_name, 
            task_name := padded_task_name, 
            argument_list := argument_list[eku], 
            status_block := status_block[eku]); 
 
  padded_application_name := PAD ( 'NKU::TRANSACTIONS', ' ', pstring_length ); 
  
  call_task(SUBMITTER_ID := submitter_id, 
            application_name := padded_application_name, 
            task_name := padded_task_name, 
            argument_list := argument_list[nku], 
            status_block := status_block[nku]); 
 
  padded_application_name := PAD ( 'WKU::TRANSACTIONS', ' ', pstring_length ); 
 
  
  call_task(SUBMITTER_ID := submitter_id, 
            application_name := padded_application_name, 
            task_name := padded_task_name, 
            argument_list := argument_list[wku], 
            status_block := status_block[wku]); 
 
  padded_application_name := PAD ( 'UL::TRANSACTIONS', ' ', pstring_length ); 
  
  call_task(SUBMITTER_ID := submitter_id, 
            application_name := padded_application_name, 
            task_name := padded_task_name, 
            argument_list := argument_list[ul], 
            status_block := status_block[ul]); 
 
 
{ Now wait for all the procedures to complete } 
 
FOR i := eku to ul DO 
   BEGIN 
     status := $ACMS$WAIT(COMP_STATUS := status_block[i]); 
     { Wait for routine to complete} 
     IF not odd(status) THEN SIGNAL(status); 
 
     IF not odd (status_block[i][0]) 
     THEN 
        signal(status_block[i][0]) 
     ELSE 
        { Tell user status result of his request } 
        LIB$PUT_OUTPUT(status_string[i]); 
   END; 
 
 
{ Call report generating routine } 
 
 padded_task_name := PAD ( 'GENERATE_REPORTS',' ', pstring_length ); 
    
 padded_application_name := PAD ( 'CMU::REPORTS', ' ', pstring_length ); 
  
 call_task(submitter_id := submitter_id, 
            application_name := padded_application_name, 
            task_name := padded_task_name, 
            argument_list :=argument_list[cmu], 
            status_block := status_block[cmu]); 
 
 
 
 status := $ACMS$WAIT(COMP_STATUS := status_block[cmu]); 
 IF not odd(status) THEN SIGNAL(status); 
 
 IF not odd (status_block[cmu][0]) 
 THEN 
    signal(status_block[cmu][0]) 
 ELSE 
    { Tell user status result of his request } 
    LIB$PUT_OUTPUT( status_string[cmu]); 
 
status := $ACMS$TERM_EXCHANGE_IO(EXCHANGE_IO_ID := exchange_io_id); 
IF not odd(status) THEN SIGNAL(status); 
 
status := $ACMS$SIGN_OUT(SUBMITTER_ID := submitter_id); 
IF not odd(status) THEN SIGNAL(status); 
 
END. {main} 


Appendix A
Superseded Services and Parameters

The first part of this appendix describes six services used in earlier versions of ACMS and provides reference material for calling these services in agent programs. These six services have been replaced by ACMS$INIT_EXCHANGE_IO and ACMS$TERM_EXCHANGE_IO. You need to use the new services and arguments for all agent programs that call tasks that perform DECforms I/O.

The new services simplify systems interface programming and simplify program maintenance. Use them with TDMS, RI, and stream services as well as with DECforms. For information regarding the new services, see Chapter 4.

ACMS supports the superseded services for agent programs that are already implemented. It also supports the superseded task I/O arguments. In new agent programs, however, use the ACMS$INIT_EXCHANGE_IO and ACMS$TERM_EXCHANGE_IO services. Whenever practical, change the superseded services to ACMS$INIT_EXCHANGE_IO and ACMS_TERM_EXCHANGE_IO in existing agent programs.

Do not mix the new services and the superseded services indiscriminately. Any attempt to use a superseded service to close a call opened with the new service results in an invalid status message. Any attempt to use the new service to close a call opened with a superseded service results in a status message of invalid.

The second part of the appendix describes parameters that were passed into the task I/O argument of the ACMS$CALL and ACMS$START_CALL services in versions of ACMS earlier than Version 3.2. Beginning with ACMS Version 3.1, instead of passing a device name or stream ID to the task I/O argument, use the exchange I/O ID for tasks that perform request I/O, stream I/O, or terminal I/O.

Table A-1 lists the superseded services and gives a brief description of each.

Table A-1 Superseded Services
Service Name Description
ACMS$OPEN_RR Opens a TDMS channel to a terminal and associates it with a submitter ID. Subsequent task selections for that submitter use the channel.
ACMS$CLOSE_RR Closes a TDMS channel to a terminal and disassociates it from a submitter ID.
ACMS$CREATE_STREAM Creates a stream and returns a stream ID.
ACMS$CONNECT_STREAM Establishes a stream connection on which the agent program and the EXC can exchange messages. This service returns a connect ID.
ACMS$DISCONNECT_STREAM Breaks a connection to a stream and invalidates the connect ID.
ACMS$DELETE_STREAM Deletes the stream. This service is normally used after ACMS$DISCONNECT_STREAM.

The rest of this appendix contains reference material for using the superseded services. The services appear in alphabetical order.

A.1 ACMS$CLOSE_RR

The ACMS$CLOSE_RR service closes a TDMS channel to a terminal and disassociates it from a submitter ID. Any active TDMS call on the channel is canceled. If the agent program uses ACMS$INIT_EXCHANGE_IO to open a channel, it must also use ACMS$TERM_EXCHANGE_IO to close the channel. If the agent program attempts to use a superseded service to close a channel opened by a new service, this results in status returns of invalid.

Note

This service has been superseded. ACMS supports this service for existing applications using TDMS. Use the ACMS$TERM_EXCHANGE_IO service in new applications.

Format

ACMS$CLOSE_RR ([channel.rlu.r],
[nullarg])

ACMS$CLOSE_RR_A ([channel.rlu.r],
[nullarg],
[comp_status.wq.r],
[efn.rbu.r],
[astadr.szem.r],
[astprm.rz.v])


Parameters

channel

The TDMS channel returned from a previous ACMS$OPEN_RR call. The agent program must supply this parameter.

nullarg

Place-holding argument. This argument is reserved for Compaq's use.

The parameters comp_status.wq.r, efn.rbu.r, astadr.szem.r, and astprm.rz.v are asynchronous service arguments. See Chapter 2 for a discussion of these parameters.


Return Status

This list summarizes each error returned by this service. Attempts to use ACMS$CLOSE_RR to close a channel opened with ACMS$INIT_EXCHANGE_IO result in a status message of invalid. Also, invalid status returns from TSS$CLOSE might be returned to the agent program. See the reference section of the VAX TDMS Reference Manual for more information on TSS$CLOSE.

The return status codes indicating success or failure of the call follow:
Status Severity Level Description
ACMS$_NORMAL Success Normal successful completion.
ACMS$_PENDING Informational Successful operation pending asynchronous completion. The final status is in the completion status block.
ACMS$_TDMSNOTINST Informational TDMS is not installed on the system.
ACMS$_INSUFPRM Error Not enough arguments were passed to this service.
ACMS$_INTERNAL Error Internal error.
ACMS$_INVCHAN Error Invalid channel---channel not known.
ACMS$_INVEFN Error The event flag was invalid.
ACMS$_SYNASTLVL Error Synchronous services may not be called from AST level.

A.2 ACMS$CONNECT_STREAM

ACMS$CONNECT_STREAM establishes a connection to a stream and returns a connect ID. Before using this service, it is necessary to create a stream with ACMS$CREATE_STREAM.

If an agent program creates and connects a stream, the agent program must call ACMS$WAIT_FOR_STREAM_IO for all tasks (except tasks that do no terminal I/O), whether or not the task performs stream I/O.

Note

This service has been superseded. ACMS supports this service for applications that have already been implemented. To simplify the writing of agent programs, and to simplify program maintenance, use the ACMS$INIT_EXCHANGE_IO service in new applications.

Format

ACMS$CONNECT_STREAM (stream_id.rq.r,
mode.rl.r,
connect_id.wq.r,
[submitter_id.rq.r])

ACMS$CONNECT_STREAM_A (stream_id.rq.r,
mode.rl.r,
connect _id.wq.r,
[comp_status.wq.r],
[efn.rbu.r],
[astadr.szem.r],
[astprm.rz.v],
[submitter_id.rq.r])


Parameters

stream_id

The identification of the stream to which you want to connect. This ID is returned by ACMS$CREATE_STREAM.

mode

The mode of this stream connection must always be set to ACMS$K_STRM_PASSIVE.

connect_id

The identification that is returned by this service to identify this stream connection. This ID is used later by ACMS$DISCONNECT_STREAM, ACMS$WAIT_FOR_STREAM_IO, and ACMS$REPLY_TO_STREAM_IO.

submitter_id

This ID is used to associate the stream ID with the submitter. The submitter_id argument is optional. You must use this parameter if the agent program calls an ACMS task that performs DECforms, TDMS, or terminal I/O, and that task calls another task that performs stream I/O.

The parameters comp_status.wq.r, efn.rbu.r, astadr.szem.r, and astprm.rz.v are asynchronous service arguments. See Chapter 2 for a discussion of these parameters.


Return Status

The return status codes indicating success or failure of the call follow:
Status Severity Level Description
ACMS$_NORMAL Success Normal successful completion.
ACMS$_PENDING Informational Successful operation pending asynchronous completion. The final status is in the completion status block.
ACMS$_SENDER_DISCONN Warning The sender has disconnected from the stream.
ACMS$_BADMODE Error The mode value specified was invalid.
ACMS$_BADSTRMID Error The stream ID is not correct; either the stream was not created, it was deleted, or the stream ID was corrupt.
ACMS$_CANOTCON Error The state of the stream does not allow for connects. The agent program must be connected before the EXC.
ACMS$_INSUFPRM Error Not enough arguments were passed to this service.
ACMS$_INVASTADR Error The AST address was invalid.
ACMS$_INVASTPRM Error The AST routine parameter was invalid.
ACMS$_INVCMPSTS Error The completion status block was invalid.
ACMS$_INVCONID Error The connect ID was invalid.
ACMS$_INVEFN Error The event flag was invalid.
ACMS$_INVMODE Error The mode of the stream was invalid.
ACMS$_INVSTRMID Error The stream ID was invalid.
ACMS$_MAXCNSCONN Error The maximum number of agent programs have already connected to the stream.
ACMS$_SYNASTLVL Error Synchronous services may not be called from AST level.
ACMS$_UNKMODE Error The mode specified was not understood by the stream arbitrator.
ACMS$_BADCONNCTLMSG Fatal Invalid function code on control message received by connection.

A.3 ACMS$CREATE_STREAM

The ACMS$CREATE_STREAM service creates a stream and returns the stream identification. It is used in conjunction with ACMS$CONNECT_STREAM. If an agent program creates and connects a stream, the agent program must call ACMS$WAIT_FOR_STREAM_IO for all tasks (except tasks that do no terminal I/O), whether or not the task performs stream I/O.

Note

ACMS$CREATE_STREAM has been superseded. ACMS supports this service for applications that have already been implemented. To simplify the writing of agent programs and to simplify program maintenance, use the ACMS$INIT_EXCHANGE_IO service in new applications.

Format

ACMS$CREATE_STREAM (mode.rl.r,
stream_id.wq.r)

ACMS$CREATE_STREAM_A (mode.rl.r,
stream _id.wq.r,
[comp_status.wq.r],
[efn.rbu.r],
[astadr.szem.r],
[astprm.rz.v])


Parameters

mode

The mode of the stream must always be set to ACMS$K_STRM_BIDIRECTIONAL.

stream_id

The stream identification that is returned by this service. The ID is passed to any task that connects to this stream.

The parameters comp_status.wq.r, efn.rbu.r, astadr.szem.r, and astprm.rz.v are asynchronous service arguments. See Chapter 2 for a discussion of these parameters.


Return Status

The return status codes indicating success or failure of the call follow:
Status Severity Level Description
ACMS$_NORMAL Success Normal successful completion.
ACMS$_PENDING Informational Successful operation pending asynchronous completion. The final status is in the completion status block.
ACMS$_BADMODE Error The mode value specified was invalid.
ACMS$_INSUFPRM Error Not enough arguments were passed to this service.
ACMS$_INVASTADR Error The AST address was invalid.
ACMS$_INVASTPRM Error The AST routine parameter was invalid.
ACMS$_INVCMPSTS Error The completion status block was invalid.
ACMS$_INVEFN Error The event flag was invalid.
ACMS$_INVMODE Error The mode of the stream was invalid.
ACMS$_INVSTRMID Error The stream ID was invalid.
ACMS$_SYNASTLVL Error Synchronous services may not be called from AST level.


Previous Next Contents Index