# Compaq TP Desktop Connector
for ACMS
Client Application Programming Guide

Previous | Contents | Index

# Chapter 6
Using Portable API Extensions for OSF/Motif

This chapter describes how to develop nonblocking desktop client programs for event-driven, multitasking environments such as OSF/Motif and X Windows.

The sample described in this chapter uses X Windows and the OSF/Motif toolkit. However, the guidelines presented here apply to any X-applications, including Open Look applications. Chapter 4 gives a useful background in the Desktop services provided in the portable API. Although the focus in that chapter is on DOS, the basic principles apply to OSF/Motif and X Windows as well. For information on designing your application with nonblocking services, see Chapter 2.

For information on configuring network transports for any of the client platforms, see Compaq TP Desktop Connector for ACMS Gateway Management Guide.

# 6.1 Event-Driven Processing

A Motif desktop client program must yield control to the X Windows system as quickly as possible so that other event processing can be handled in a timely way. The following TP Desktop Connector nonblocking services provide methods to facilitate yielding control:

- acmsdi_dispatch_message
  Receives requests and responses from the gateway and dispatches the corresponding procedures.
- acmsdi_complete_pp
  Sends responses to the gateway when presentation procedures complete.

Figure 6-1 shows the sequence of processing in an event-driven desktop client program.

Figure 6-1 Event-Driven Desktop Client Program Processing

When the user selects a task from a menu, the desktop client program calls the acmsdi_call_task service to initiate an ACMS task. In the nonblocking environment, you specify nonblocking parameters in the call (see Section 9.5). For example, the address of a completion routine is a nonblocking parameter that you can include in the desktop client program. The TP Desktop Connector client service calls the completion routine when the TP Desktop Connector Gateway for ACMS completes the task. Because the completion routine parameter is specified in the call, the TP Desktop Connector client service is treated like a nonblocking service and returns control to the desktop client program immediately after the start task request is sent to the TP Desktop Connector gateway. The desktop client program does not wait for the gateway to request ACMS software to start a task in an ACMS application. Instead, the desktop client program returns control to XtMainLoop for more event processing.

The TP Desktop Connector client service also returns a call identification that the desktop client program supplies to the acmsdi_complete_pp service. The services use the call identification to associate an active call with a submitter. Note that TP Desktop Connector supports, at most, one active task for each submitter.

Because of an exchange step in the I/O task, the ACMS system starts a transceive operation. The gateway sends a message to the desktop client program to start a presentation procedure.

The acmsdi_dispatch_message service runs as part of the polling mechanism established by the desktop client program. The acmsdi_dispatch_message service polls for the message and, when the message is received, calls the customer-written presentation procedure acmsdi_transceive. The acmsdi_transceive routine runs, saves pointers to the workspaces, displays a dialog box, and returns control to X Windows without the user having to signal completion.

The user then has an opportunity to edit or add data to a form in the context of an exchange step. When the user later clicks on OK to signal completion, the desktop client program uses the saved workspace pointers to store the user-entered data, and calls the acmsdi_complete_pp service to send the workspaces and response status to the gateway. (The desktop client program does not wait for a response from the gateway. It returns control to XtMainLoop as soon as possible.) Meanwhile, the gateway passes to the ACMS task the workspaces and the status from the completion of the presentation procedure.

When the task completes on the ACMS system, the gateway sends the end task message to the desktop system. The TP Desktop Connector client services dispatch the end task message by calling a completion routine in the desktop client program. This completion routine is dispatched by the polling mechanism and acmsdi_dispatch_message.

The gateway sends a message to the desktop client program under two conditions:

- To signal the completion of a TP Desktop Connector client service
  The desktop client program supplies the address of completion routines in the nonblocking forms of the acmsdi_sign_in, acmsdi_call_task, and acmsdi_sign_out services.
- To process an exchange step in the task
  Client services define entry points for presentation procedures that correspond to all possible exchange steps. The desktop client program supplies the code that handles these presentation procedures.

The TP Desktop Connector client services dispatch the gateway messages to the desktop client program by the polling mechanism established.

# 6.2 Guidelines for Developing X Windows Desktop Client Programs

The following list summarizes general requirements and guidelines for developing X Windows nonblocking desktop client programs:

- Write procedures to use nonblocking TP Desktop Connector client services (see Section 6.4).
  Organize functions so that every call to a TP Desktop Connector service or a customer-written presentation procedure has a parallel completion routine.
- Set up polling within the desktop client program (see Section 6.4.2).
  Set up a mechanism to retrieve desktop messages. Use this mechanism to periodically gain control and call the acmsdi_dispatch_message service to retrieve messages from the gateway.
- Establish session context in the desktop client program (see Section 6.4.3).
  Set up structures for handling multiple sessions. Certain data must be maintained as context for a current session and inactive sessions.

- Write presentation procedures to coexist in the nonblocking environment (see Section 6.6).
  You must complete all presentation procedures using the acmsdi_complete_pp service.
- Convert data as required between the desktop system and the ACMS system (see Section 4.1.3).

Optionally, you can do the following when developing a desktop client program:

- Write an action routine to perform version checking.
  The module version.c shows a stub version-checking routine (see Section 4.3).

The remainder of the chapter explains the guidelines using code from the AVERTZ sample desktop client program.

# 6.3 AVERTZ Sample Desktop Client Program for X Windows

The Motif AVERTZ sample desktop client program is written in C and follows the standards and practices outlined in the OSF/Motif Style Guide. The program uses a main window, icons, and dialog boxes to interact with the user.

## 6.3.1 AVERTZ Components for X Windows

A nonblocking X Windows desktop client program has some of the same high-level components as a blocking Desktop client (see Figure 6-2). Note the addition of the polling mechanism as well as the application-specific presentation procedures, which are split into two parts.

The m_avertz.exe program includes the following functional modules:

- m_avertz.c
  Contains the main window support routines and the program initialization.
- m_avertzpp.c
  Defines all application-specific presentation procedures for the AVERTZ desktop client program.
- m_resvform.c
  Manages the reservation form for interaction with the user in the AVERTZ reserve task.

- m_session.c
  Initializes and controls multiple user sign-ins and manages windows, icons, and menus for multiple user sessions.
- m_disable.c, m_enable.c, m_receive.c, m_request.c, m_send.c, and m_transceive.c
  Handle the generic presentation procedures.

Figure 6-2 TP Desktop Connector Sample Components for X Windows

The desktop client program allows the user to maintain multiple sign-ins with the AVERTZ application, VR_DA_APPL. The program controls each sign-in by associating session context with the user sign-in data.

The desktop client program user interface presents menus with which the user interacts to sign in to and out of the ACMS system, run ACMS tasks, and control sessions:

- Session menu
  Signs the user in to and out of the ACMS system.
- Rental menu
  Lets the user start tasks.
- Search menu
  Allows the user to select site information from a list of available sites.
- Select menu
  Allows the user to activate a session through a list of active sessions rather than by selecting an icon.

Program-defined icons represent sessions. The user can double click on an icon to bring up forms associated with a specific session. The icons are also visual clues to active and inactive sessions.

## 6.3.2 AVERTZ Component Processing Flow

The m_avertz.c module contains the program initialization, XtMainLoop, and support for the main window. The following important functions are performed:

- main
  Initializes the Motif toolkit, registers callbacks, fetches and displays the main window, and polls for X-events.
- client_init
  Sets up the polling mechanism for soliciting TP Desktop Connector messages.

- CreateReservation
  Invoked when the user selects the Create Reservation menu item. Starts the Reserve task in the ACMS application, VR_DA_APPL, by calling acmsdi_call_task.

The m_session.c module contains the following session creation and control functions:

- NewSession
  Invoked when the user presses the OK button in the session login dialog box. Creates a new session, signs the user in to the ACMS system with the acmsdi_sign_in service, and adds the session to the list of active sessions.
- NewSession_Complete
  Called when the acmsdi_sign_in service completes. Completes processing of the NewSession function and updates the user interface accordingly.
- ExitSession and ExitSessionComplete
  Ends a session by calling the acmsdi_sign_out service and cleaning up session data structures.
- SessionTask_Complete
  Called when a task for a given session completes. Updates the user interface accordingly.

The New command in the session menu presents a dialog box to enable the user to sign in to the ACMS system, thereby creating a new AVERTZ session. After the user is signed in to the ACMS system, the desktop client program maintains session information to track, for example, the association between the form (or forms) of a given session and the corresponding ACMS submitter identification. The program also activates other menus to allow the signed-in user to select ACMS tasks. A session can have only one active task at any given time, but a user can sign in to the ACMS system many times, allowing multiple tasks to run simultaneously.

Individual modules handle the generic presentation procedures. For example, m_transceive.c handles the acmsdi_transceive presentation procedure called from the ACMS system, validates the parameters, and dispatches control to the appropriate application-specific presentation procedure.

The m_avertzpp.c module handles all application-specific presentation procedures for the AVERTZ desktop client program. Each presentation procedure comprises an initial routine, for example, Trans_List3_List2, and a completion routine, for example, End_Trans_List3_List2. The generic presentation procedures call the initial routine (the first part of the presentation procedure), which generally displays the data from the workspaces sent by the ACMS system and returns. Control returns to XtMainLoop so that the user can enter and receive data.

When the user signals completion (done entering data) for this presentation procedure, the corresponding completion routine is called. It collects the user-entered data and sends it to the ACMS system to complete processing of the presentation procedure.

The m_resvform.c module manages the reservation form for the reserve task, including field validation and initialization. When the user clicks on the OK or cancel button in the reservation form, the ResvFormExchangeComplete() routine dispatches the completion routine of the current presentation procedure. The following series of figures (Figure 6_3, Figure 6_4, Figure 6_5, and Figure 6-6) present the flow of a nonblocking service.

Figure 6-3 shows the user selecting the Create Reservation task from the Rental menu.

Figure 6-3 User Selects a Task

The following callouts describe the actions in Figure 6-3:

1. The end user selects the CreateReservation command.
2. The X Windows system indicates this event by sending a ButtonPress event to the X Windows event queue.
3. In the application's main() module, XtMainLoop continuously looks at the X-event queue for incoming events. XtMainLoop pulls the ButtonPress event off the event queue.
4. XtMainLoop determines that the widget callback registered for this event is the function CreateReservation(). XtMainLoop then dispatches the CreateReservation() function in response to the event.

Figure 6-4 shows the flow of code in the nonblocking service.

Figure 6-4 Nonblocking Service

The following callouts describe the flow of code in Figure 6-4:

1. To support nonblocking services, the application sets up a mechanism to call acmsdi_dispatch_message at periodic intervals. This is normally done at the application's initialization time. The client_init() function sets up the mechanism that periodically calls check_for_messages().
2. Inside the CreateReservation() function, the application initiates the VR_RESERVE_TASK task by making a call to acmsdi_call_task. To indicate that this is a nonblocking call, the completion routine parameter is set to the function pointer, SessionTask_Complete. The application passes the current_session_ptr as context to be received back when the completion routine SessionTask_Complete is called.
3. When acmsdi_call_task is invoked, TP Desktop Connector client services send a Start Task message to the ACMS application. When the ACMS application receives the message, VR_RESERVE_TASK begins.
4. When VR_RESERVE_TASK completes, TP Desktop Connector services send an End Task message to the TP Desktop Connector message queue on the desktop system.
5. Meanwhile, check_for_messages() is being invoked at regular intervals. When it calls acmsdi_dispatch_message, TP Desktop Connector client services looks for incoming messages on the message queue. When it pulls the End Task message off the message queue, it determines that the completion routine that was specified for this service is SessionTask_Complete().
6. Then acmsdi_dispatch_message dispatches the function SessionTask_Complete() in response to the message. The context specified on the acmsdi_call_task call is passed back as a parameter. The application can use this application-specific context, for example, to have the user interface reflect that the task completed.

Figure 6-5 shows the I/O processing of a nonblocking service.

Figure 6-5 I/O Processing for a Nonblocking Service/Part 1

The following callouts describe the I/O processing flow for a task that has just been invoked:

1. In Figure 6-5, the first exchange step of VR_RESERVE_TASK is Transceive List3 List2. When this exchange step is encountered, an acmsdi_transceive message is sent to the TP Desktop Connector Message Queue on the desktop system.
2. Meanwhile, acmsdi_dispatch_message() is being called at regular intervals.
3. When TP Desktop Connector pulls the start transceive message off the message queue, it dispatches the presentation procedure, acmsdi_transceive().
4. The acmsdi_transceive routine looks at the values of the send_record_id and the receive_record_id to determine which specific transceive procedure is being requested. (In Figure 6-5, Transceive_List3_List2 is the specific transceive procedure specified in the ACMS task, so the send_record_id is List 3 and the receive_record_id is List 2.) Before leaving the acmsdi_transceive routine, the application must save the pointers to the receive workspaces. These pointers are needed later when the application is ready to load the receive workspaces with the user's data input.
5. The specific transceive routine Trans_List3_List2() is called.
6. The specific transceive routine puts up a form and enables the fields associated with this transceive exchange. When this routine completes, control returns to XtMainLoop().

Figure 6-6 shows the form displayed by the Trans_List3_List2() routine.

Figure 6-6 I/O Processing for a Nonblocking Service/Part 2

The following callouts described the processing in Figure 6-6:

1. The user enters data into various fields of the form, and when finished entering data, the user clicks on the OK button.
2. X Windows puts this ButtonPress event on the X-event queue.
3. XtMainLoop() pulls the ButtonPress event off the event queue.
4. XtMainLoop() determines that the callback registered for this event is in the function End_Trans_List3_List2().
5. An intermediate routine called ResvFormExchange Complete is invoked. It determines which specific presentation procedure is completing.
6. In End_Trans_List3_List2, the pointers to the receive workspaces are retrieved (the application stored them away at the beginning of the transceive processing). See Figure 6-5, Callout 4. The user's data input is retrieved from the form and loaded into the receive workspaces.
7. When the receive workspaces are ready to be sent back to ACMS, the application notifies the Desktop client services by issuing a call to acmsdi_complete_pp().
8. TP Desktop Connector then sends the workspaces and a completion status back to the ACMS application.

# 6.4 Writing Client Procedures Using Nonblocking Services

The following sections describe how to structure procedures that use nonblocking services.

## 6.4.1 Calling Nonblocking Services

Nonblocking forms of the services have the following differences from blocking forms:

- The routine calling the desktop service supplies the address of a completion routine, the context, and the completion status in the service call.
  When TP Desktop Connector receives the call-completion message from the gateway, TP Desktop Connector calls the desktop client program completion routine.
- The TP Desktop Connector client service returns control to the desktop client program after sending a request to the gateway.
  This return allows the desktop client program to yield control to X Windows, so that event processing can continue.
- Because the nonblocking services return control before a request completes, the desktop client program must not release storage for service argument data until after it calls the completion routine.
  If the calling routine returns before the service completes, the routine must not use volatile memory for service arguments. For example, in the C language, volatile memory includes local (automatic) variables and the arguments passed on routine calls.

The desktop client program periodically calls acmsdi_dispatch_message() to check for pending replies or requests from the gateway. When the client service completion message arrives, the acmsdi_dispatch_message() calls the completion routine in the desktop client program.

Example 6-1 shows the calls in the m_session.c module to the acmsdi_sign_in service that creates a new session, and to the companion completion routine NewSession_Complete that completes the service.

Example 6-1 Nonblocking Service Call and Completion Routine

    extern void NewSession(
           Widget    widget,
           int      *client_data,
                  XtPointer call_data)
    {

       .
       .
       .

        status = acmsdi_sign_in(
                    session_ptr->node,
                    session_ptr->username,
                    session_ptr->password,
                    (long) 0,
                    session_ptr->submitter_id,
                    &session_ptr->completion_status,
                    NewSession_Complete,             (1)
                    (void *) session_ptr);

         if (status == ACMSDI_PENDING)  (2)
         {
       .
       .
       .
    extern void NewSession_Complete(void *call_context)  (3)
    {
      session_type *session_ptr;
      Widget        session_icon;
      int           i;

      /* Get Session Node For This Sign In Completion */

      session_ptr = (session_type *) call_context;

      /*
      ** Check ACMS Return Status
      **  - If failure occurred, put up the error message and
      ** delete session from session list.
      */

      if (session_ptr->completion_status != ACMSDI_NORMAL)
      {
        DisplayDesktopErrorMessage(session_ptr, session_ptr->completion_status);

        delete_session_context(session_ptr);

      }
      else
      {

       .
       .
       .

The acmsdi_sign_in service call is triggered by the user selecting the OK button in the New Session dialog box:

1. The call specifies the completion routine address.
   Specifying the completion routine NewSession_Complete indicates a nonblocking service.
2. The desktop client program checks for ACMSDI_PENDING to ensure that the call is sent to the ACMS system.
   The user at this point is not signed in to the ACMS system. If a status other than ACMSDI_PENDING is returned, the completion routine is not called.
3. When the sign-in completes, the completion message arrives and the desktop service calls the completion routine to handle the status.

After the acmsdi_sign_in service returns ACMSDI_PENDING, the desktop client program receives a submitter identification that is used on subsequent calls. If a nonblocking call to a TP Desktop Connector client service routine returns a status code other than ACMSDI_PENDING, the completion routine for that call is not invoked.

Previous | Next | Contents | Index