# Compaq TP Desktop Connector
for ACMS
Client Application Programming Guide

Previous | Contents | Index

## 4.1.4 Preventing Concurrent Use

TP Desktop Connector portable API client services are serialized (nonreentrant) portable API client services do not allow the concurrent execution of two or more calls from a given submitter or on a given gateway connection. TP Desktop Connector prevents concurrent calls by rejecting calls made to the portable API client services while the API is actively executing instructions from the calling submitter or on the target connection from a different submitter. TP Desktop Connector does not reject calls if the API is waiting for a reply from the gateway, thereby, allowing nonblocking execution to proceed.

To avoid serialization violations, do not issue TP Desktop Connector calls from TP Desktop Connector presentation procedures, completion routines, or any asynchronous routines (for example, ASTs or UNIX signals). The only exception is the acmsdi_complete_pp call, which you must issue from the presentation procedure in nonblocking environments.

Table 4-2 lists the status codes returned to the caller when TP Desktop Connector rejects a call due to a serialization violation.

Table 4-2 Status Codes Returned Due to Serialization Violations
Status | Call Type Currently Executing
--- | ---
ACMSDI_CALLACTV | acmsdi_call_task
ACMSDI_CANCELACTV | acmsdi_cancel
ACMSDI_DISPATCHACTV | acmsdi_dispatch_message
ACMSDI_SIGNINACTV | acmsdi_sign_in
ACMSDI_SIGNOUTACTV | acmsdi_sign_out

# 4.2 Generating Workspaces for the Client

TP Desktop Connector provides the command file MAKE_RECORDS.COM, which generates workspaces for the C and COBOL environments.

## 4.2.1 Generating Workspace Definitions

The MAKE_RECORDS.COM utility uses CDD to generate the record definitions of ACMS workspaces needed by client applications. This utility can generate record definitions of workspaces for:

- C client applications
- COBOL client applications

When you define workspaces in CDD, you can share their definitions between the ACMS application and the client program. Using the CDD-generated record definitions, the chances of mismatches between the ACMS application workspace definitions and the client program workspace definitions are greatly reduced.

## 4.2.2 Using the MAKE_RECORDS.COM Utility

The MAKE_RECORDS utility is run on OpenVMS to generate either C files, COBOL files, or both, containing the workspace definitions. These files can then be transferred down to the desktop system and incorporated into the TP Desktop Connector client program.

The MAKE_RECORDS utility presumes that you have stored your ACMS workspace definitions in a specific CDD directory. For example, Figure 4-2 shows the CDD directory structure for the AVERTZ sample application.

Figure 4-2 CDD Directory Structure

The definitions for each field of every AVERTZ workspace are defined in the Field directory. All of the AVERTZ workspaces are then defined (using the field definitions) in the Wksp directory.

To generate the C structure definitions for all the AVERTZ workspaces, invoke the following command (on OpenVMS):

    $ @MAKE_RECORDS avertz_cdd:avertz_dev.wksp  C

where:

- avertz_cdd is a logical name pointing to the specific Oracle CDD dictionary.
- avertz_dev.wksp is the Oracle CDD directory containing the workspaces.
- C specifies the C syntax for the record definition.

For each workspace defined in the avertz_dev.wksp directory, a C header file is generated in the current directory.

To generate COBOL record definitions for all of the AVERTZ workspaces, invoke the following command:

    $ @MAKE_RECORDS avertz_cdd:avertz_dev.wksp  COBOL

where:

- avertz_cdd is a logical name pointing to the specific Oracle CDD dictionary.
- avertz_dev.wksp is the Oracle CDD directory containing the workspaces.
- COBOL specifies the COBOL syntax for the record definition.

For each workspace defined in the avertz_dev.wksp directory, a COBOL file is generated in the current directory.

## 4.2.3 Generating Individual Workspace Definitions

You can also generate a record definition for a specific workspace using MAKE_H.COM or MAKE_COBOL.COM.

As an example, one of the AVERTZ workspaces defined in CDD is VR_SITES_WKSP. This workspace's record definition is located in the CDD directory, avertz_cdd:avertz_dev.wksp.

To generate a C header file for VR_SITES_WKSP, specify the following:

    $ DEFINE CDD$DEFAULT avertz_cdd:avertz_dev.wksp
    $ @MAKE_H vr_sites_wksp

where:

- avertz_cdd is a logical name pointing to the specific CDD dictionary
- avertz_dev.wksp is the CDD directory containing the workspace record
- vr_sites_wksp is the record name

This definition generates VR_SITES_WKSP.H in the current directory.

To generate a COBOL file for VR_SITES_WKSP, specify the following:

    $ DEFINE CDD$DEFAULT avertz_cdd:avertz_dev.wksp
    $ @MAKE_CBL vr_sites_wksp

where:

- avertz_cdd is a logical name pointing to the specific CDD dictionary
- avertz_dev.wksp is the CDD directory containing the workspace record
- vr_sites_wksp is the record name

This definition generates VR_SITES_WKSP.CBL in the current directory.

## 4.2.4 Coding Workspace Fields

If workspaces are manipulated by C in the desktop client program, some conversions are necessary. These conversions are the responsibility of the desktop client program.

### 4.2.4.1 Initializing Workspaces from ACMS

Character strings in workspaces coming from the TP Desktop Connector Gateway for ACMS do not have a NULL terminator. If you use regular C functions in the desktop client program to manipulate the strings in the workspace, you need to add NULL terminators. See the examples in the AVERTZ sample applications, particularly the convert_* functions in wkspaces.c and m_wkspaces.c. (An alternative is to use functions such as memset and memcpy that do not expect the NULL terminator.)

### 4.2.4.2 Initializing Workspaces to ACMS

Character strings in workspaces going back to the TP Desktop Connector Gateway for ACMS must have NULL terminators removed and be padded with spaces. The desktop client program should initialize these workspace fields to their expected initial values, for example, zeros or spaces. Initialization can be done using one of the following methods:

- Explicitly initialize each field in each workspace.
  If the desktop client program is written in C, use the memset function. If using COBOL, then the strings probably are not NULL terminated. If the desktop client program is written in COBOL, use the MOVE statement.

- Keep a copy of each workspace containing fields preset to their initial values.
  At the beginning of the workspace processing, use the C memcpy function or the COBOL MOVE statement to copy each field to its corresponding workspace.

Avoid using the C strcpy function to initialize workspaces or set values of fields in workspaces. If you do use strcpy, make sure that the NULL terminator is replaced with a blank character before the workspace is sent back. See examples in the AVERTZ sample (the init_* functions in wkspaces.c or m_wkspaces.c). In most cases, the ACMS application is not expecting NULL-terminated strings. Use the C memset and memcpy functions to set the values of workspaces.

## 4.2.5 Using Data Compression with the Portable API

TP Desktop Connector provides the call option, ACMSDI_CALL_OPT_COMPRESS_WKSPS, to activate data compression for task calls. This call option specifies whether or not to apply data compression to workspaces. The following sections describe how to activate data compression. In addition, TP Desktop Connector also provides a Data Compression Monitor that allows you to gather statistics on the effectiveness of the compression. See Section 4.2.6 for a description of this facility.

### 4.2.5.1 Activating Data Compression

The ACMSDI.H include file contains the ACMSDI_CALL_OPTION_TYPE enumeration. The call option type is included in this enumeration to support the activation of data compression for a task call. The symbol for the call option is ACMSDI_CALL_OPT_COMPRESS_WKSPS. Example 4-1 shows the ACMSDI_CALL_OPTION_TYPE enumeration as it appears in ACMSDI.H:

Example 4-1 Compression Call Option Type

    /*
    ** Call task options
    */
    typedef enum {
        ACMSDI_CALL_OPT_END_LIST = 0,   /* end the options list */
        ACMSDI_CALL_OPT_OPTIMIZE_WKSPS, /* optimize network traffic on      */
                                        /* passed workspaces                */
        ACMSDI_CALL_OPT_ENABLE,         /* Pointer to enable function       */
        ACMSDI_CALL_OPT_DISABLE,        /* Pointer to disable function      */
        ACMSDI_CALL_OPT_SEND,           /* Pointer to send function         */
        ACMSDI_CALL_OPT_RECEIVE,        /* Pointer to receive function      */
        ACMSDI_CALL_OPT_TRANSCEIVE,     /* Pointer to transceive function   */
        ACMSDI_CALL_OPT_REQUEST,        /* Pointer to request function      */
        ACMSDI_CALL_OPT_CHECK_VERSION,  /* Version checking routine         */
        ACMSDI_CALL_OPT_PASS_TID,       /* TID of distributed transaction   */
        ACMSDI_CALL_OPT_COMPRESS_WKSPS  /* activate workspace compression   */
    } ACMSDI_CALL_OPTION_TYPE;

Prior to issuing acmsdi_call_task, the application program activates data compression by declaring an ACMSDI_CALL_OPTION array and initializing one of the array's elements with the call option type as shown in the following code example:

    ACMSDI_CALL_OPTION call_option[2];   /* call option array */

        call_option[0].option = ACMSDI_CALL_OPT_COMPRESS_WKSPS;
        call_option[1].option = ACMSDI_CALL_OPT_END_LIST;

The ACMSDI_CALL_OPTION array is passed as an argument on acmsdi_call_task.

### 4.2.5.2 Specifying Data Compression for Workspaces

If you do not use optimized (unidirectional) workspaces for the task for which compression is active, data compression is attempted for all workspaces associated with the task call. In this case, the ACMSDI_WORSKPACE structure is used to describe each workspace.

When data compression is activated for a call using optimized workspaces, you can specify compression for individual workspaces with the ACMSDI_INIT_WORKSPACE_OPT macro. This macro initializes an ACMSDI_WORKSPACE_OPT structure. When data compression is activated, use one ACMSDI_WORKSPACE_OPT structure to describe each workspace associated with the task call; do not use the ACMSDI_WORKSPACE structure if you want to specify compression for individual workspaces.

The following example shows the ACMSDI_WORKSPACE_OPT structure as defined in ACMSDI.H:

    typedef struct {
        unsigned int length;
        ACMSDI_ACCESS_TYPE access;
        void *data;
    } ACMSDI_WORKSPACE_OPT;

The data type ACMSDI_ACCESS_TYPE is defined as a single byte. ACMSDI_ACCESS_TYPE can have one of six values as defined in ACMSDI.H:

    #define ACMSDI_ACCESS_READ    '1'   /* read-only access */
    #define ACMSDI_ACCESS_WRITE   '2'   /* write-only access */
    #define ACMSDI_ACCESS_MODIFY  '3'   /* modify (read and write) */
    #define ACMSDI_ACCESS_READ_COMPRESS '4'   /* read-only access with compression*/
    #define ACMSDI_ACCESS_WRITE_COMPRESS '5'  /* write-only access with compression*/
    #define ACMSDI_ACCESS_MODIFY_COMPRESS '6' /*modify (read and write) with compression*/
       .
       .
       .
    typedef char ACMSDI_ACCESS_TYPE;

Access types 4, 5, and 6 support data compression.

These values specify that TP Desktop Connector client services routines and/or ACMS are to attempt to compress the workspace. Table 4-3 illustrates the values which can apply to data elements whose type is ACMSDI_ACCESS_TYPE:

Table 4-3 Portable API Access Types
Value | Specification | Description
--- | --- | ---
1 | ACMSDI_ACCESS_READ | read-only access
2 | ACMSDI_ACCESS_WRITE | write-only access
3 | ACMSDI_ACCESS_MODIFY | modify access
4 | ACMSDI_ACCESS_READ_COMPRESS | read-only/compress
5 | ACMSDI_ACCESS_WRITE_COMPRESS | write-only/compress
6 | ACMSDI_ACCESS_MODIFY_COMPRESS | modify/compress

Using the ACMSDI_INIT_WORKSPACE_OPT macro, you initialize the ACMSDI_WORKSPACE_OPT structure for each workspace before issuing acmsdi_call_task. Then pass the ACMSDI_WORKSPACE_OPT array as an argument on acmsdi_call_task.

Example 4-2 illustrates a task call passing four workspaces. The access types for the workspaces are as follows:

- control_wksp --- read-only
- empl_updates --- read-only & compressed
- empl_record --- write-only & compressed
- dept_record --- modifiable & compressed

Example 4-2 Portable API Task Call Passing Four Workspaces

    struct {
        char ctrl_key[5];
        char error_msg[80];
    } control_wksp;

    struct {
        int employee_number;
        char address_line_1[40];
        char address_line_2[40];
        char address_line_3[40];
        int insurance_code;
    } empl_updates;

    struct {
        int employee_number;
        int dept_number;
        char first_name[20];
        char last_name[25];
        char address_line_1[40];
        char address_line_2[40];
        char address_line_3[40];
        int number_dependents;
        int insurance_code;
    } empl_record;

    struct {
        int dept_number;
        char dept_name[40];
        char manager[25];
        int number_employees;
    } dept_record;

    ACMSDI_CALL_OPTION call_option[3];  /* call option array */
    ACMSDI_WORKSPACE_OPT wksp_array[4]; /* workspace array */

        call_option[0].option = ACMSDI_CALL_OPT_OPTIMIZE_WKSPS;
        call_option[1].option = ACMSDI_CALL_OPT_COMPRESS_WKSPS;
        call_option[2].option = ACMSDI_CALL_OPT_END_LIST;
        ACMSDI_INIT_WORKSPACE_OPT (wksp_array[0],
                                   control_wksp,
                                   ACMSDI_ACCESS_READ);
        ACMSDI_INIT_WORKSPACE_OPT (wksp_array[1],
                                   empl_updates,
                                   ACMSDI_ACCESS_READ_COMPRESS);
        ACMSDI_INIT_WORKSPACE_OPT (wksp_array[2],
                                   empl_record,
                                   ACMSDI_ACCESS_WRITE_COMPRESS);
        ACMSDI_INIT_WORKSPACE_OPT (wksp_array[3],
                                   dept_record,
                                   ACMSDI_ACCESS_MODIFY_COMPRESS);
        acmsdi_call_task (&sub_id,
                          &call_option,  /* call option array */
                          "MYTASK",
                          "MYAPPL",
                          "",
                          stat_msg,
                          4,             /* number of workspaces */
                          &wksp_array,   /* workspace array */
                          &call_id,
                          0,0,0);

## 4.2.6 Data Compression Monitor

The Data Compression Monitor provides you with statistics about the effectiveness of TP Desktop Connector data compression. When the monitor is activated, information on each task call and each exchange step callback is gathered in a monitor log file from which you can generate a variety of reports.

You can request reports with summaries for any combination of the following entities:

- Submitter node
- User
- ACMS application
- ACMS task

The following information is captured for each task call and for each exchange step callback:

- Date and time that the call or the callback occurred
- Submitting node identifier
- Signed-in user identifier
- ACMS application name
- ACMS task name
- Call type (task call or exchange step callback type)
- Number of workspaces
- For each workspace:
  - Access code (READ, WRITE or MODIFY)
  - Compression code (Compressed, Uncompressable, or No Attempt to Compress)
  - Uncompressed length
  - Compressed length

### 4.2.6.1 Activating and Deactivating Compression Monitoring

To activate compression monitoring, on the node where the TP Desktop Connector Gateway for ACMS is running, define the following logical name:

    $ DEFINE/SYSTEM ACMSDI$COMPRESSION_STATS Y

Note You do not need to bring down the TP Desktop Connector Gateway for ACMS before defining this logical name.

When you define the logical ACMSDI$COMPRESSION_STATS with a value of Y or y, compression data is written to the compression monitor log file, ACMSDI$COMPRESSION.LOG. This file is written to the SYS$ERRORLOG: directory. As each ACMS task call is initiated on the server node, the gateway checks to see if the ACMSDI$COMPRESSION_STATS logical is defined. If the logical is defined and if its value is Y or y, data is gathered for the task call and for any exchange step callbacks that may be associated with the execution of the task.

To deactivate compression monitoring, redefine the logical name, ACMSDI$COMPRESSION_STATS, with a value of N or n as follows:

    $ DEFINE/SYSTEM ACMSDI$COMPRESSION_STATS N

Or, you can deassign the logical name as follows:

    $ DEASSIGN/SYSTEM ACMSDI$COMPRESSION_STATS

Either method causes the gateway to stop gathering compression data for tasks as they are initiated. However, compression data continues to be gathered for any task that is executing at the time of deactivation until that task has finished executing.

### 4.2.6.2 Creating Compression Activity Reports

To create compression activity reports, execute the Data Compression Monitor (DCM) activity reporting program by entering the following at the DCL prompt:

    $ MCR ACMSDI$DCM

Note DCM writes the report to the SYS$OUTPUT device.

DCM responds with the following prompt:

    DCM>

You can select reports for all activities, or for an activity that occurred within a given timeframe. In addition, you can select reports for any combination of the following:

- Submitter node
- User ID
- ACMS application
- ACMS task

For example, to request a report for all activities from node "MYPC", running ACMS task "MYACMSTASK", from 15-SEP-1998 at 12 noon through 16-SEP-1998 at 11:45 AM, enter the following:

    DCM> LIST /SINCE=15-SEP-1998:12:00 /BEFORE=16-SEP-1998:11:45 /NODE=MYPC - /TASK=MYACMSTASK

This report shows details of all task calls for the selected task from the selected node in the given timeframe, sorted chronologically, with details for each workspace. The report also contains a summary showing the total number of bytes in the uncompressed workspaces, their compressed sizes, and the number of bytes by which the workspace sizes were reduced.

If you need only the summary information, you can add the /SUMMARY qualifier to the request. You can also direct reports to a file (as opposed to being displayed on your screen) with the /OUTPUT qualifier.

See Compaq TP Desktop Connector for ACMS Client Services Reference Manual for a description of the LIST command.

### 4.2.6.3 Creating Customized Reports

DCM provides only one report type. However, by using the SELECT command, you can select combinations of records from the compression monitor log file and write them to a different file. You can then create a program that sorts, summarizes, and displays these records in any way you require. For example, you may want a report sorted by task name, instead of chronologically as the standard reports provide, or a report that contains only tasks associated with a given ACMS application. The following command selects records associated with the ACMS application, MYAPP, and writes the records to a file named MYAPP.DAT:

    $ ACMSDI$DCM
    DCM> SELECT MYAPP.DAT /APPLICATION=MYAPP

You can sort the file MYAPP.DAT, ordering it by (for example) ACMS Task, Node Name, and User ID. The sorted output can then be submitted to a user-written reporting program.

The name of the Data Compression Monitor log file is:

- SYS$ERRORLOG:ACMSDI$COMPRESSION.LOG

Example 4-3 shows the layout of the records as they appear in the monitor log file and in the files created using the SELECT command.

The record consists of a fixed section of 109 bytes followed by one section for each workspace of 12 bytes. All fields are of data type char.

Example 4-3 Record Layout

    The record format is:

    Field name       Offset   Length  Description
    ---------------  ------   ------  -------------------------------------
    Date/time stamp    0        24     Date and time record was written to
                                       the log in the following format:
                                           www mmm dd hh:mm:ss yyyy
                                           www  = day of week
                                           mmm  = month
                                           dd   = day of month
                                           hh   = hour
                                           mm   = minute
                                           ss   = second
                                           yyyy = year
                                           Example:
                                              Fri Sep 18 13:33:16 1997

    Node                24      20     Node identification. For TCP/IP this
                                       is the IP address.

    User Name           44      20     Identifier of the signed-in user.

    Application Name    64      20     ACMS application name.

    Task Name           84      20     ACMS task name.

    Call Type           104     1      Code which identifies the type of
                                       call:
                                          C = Task Call
                                          S = Send Exchange Step
                                          R = Receive Exchange Step
                                          T = Transceive Exchange Step
                                          D = TDMS Exchange Step

    Direction Code      105     1      Direction in which the message was
                                       sent:
                                          D = Message sent to desktop device
                                          H = Message sent to OpenVMS host

    Workspace Count     106     3      Number of workspaces

    Following the workspace count there is one 12-byte section for each workspace,
    starting at offset 109, in the following format:

    Uncompressed Length   0      5     Length of workspace in uncompressed
                                       state.

    Compressed Length     5      5     Length of workspace in compressed
                                       state.

    Access Code          10      1     One of the following:
                                          R = Read Access
                                          W = Write Access
                                          M = Modify Access

    Compression Code     11      1     One of the following:
                                          C = Workspace was compressed
                                          U = Workspace was uncompressable
                                          N = No attempt was made to compress
                                              this workspace

Note To keep the record length small, only the first 20 bytes of the User ID, Application Name and Task Name fields are captured. The fields are left-justified and, if necessary, padded with blanks on the right.

See Compaq TP Desktop Connector for ACMS Client Services Reference Manual for the Data Compression Monitor commands.

Previous | Next | Contents | Index