DIGITAL TP Desktop Connector
for ACMS
Client Application Programming Guide


Previous Contents Index

8.2.5 Ending an Active Session

To end an active session, the desktop client program calls DBEnd as shown in Example 8-12.

Example 8-12 Calling DBEnd

short    status;        /* Status Variable */ 
long     sessid1;       /* Session Id   */ 
 
status = DBEnd (sessid1, NULL); 

The DBEnd service also deletes a zombie session created by the DBInit service.

If an error status is returned on the DBEnd service, the session resources are still returned to the Macintosh system and any active connection is broken. You cannot call the DBGetErr service to obtain additional information about an error on the DBEnd service.

In the HyperCard implementation of AVERTZ, DBEnd is called by the ACMSEnd XFCN, invoked in the main stack script, as shown in Example 8-13.

Example 8-13 Calling ACMSEnd

on killSession sessionID 
   .
   .
   .
        put ACMSEnd (sessionID) into stat 
   .
   .
   .
end killSession 

8.2.6 Getting Error Information

A desktop client program calling a TP Desktop Connector client service on the Macintosh typically expects a return status of NoErr.1 If the desktop client program receives an unexpected return status, it can usually call the DBGetErr service to retrieve additional information concerning the error condition. For the specified session identification, the DBGetErr service returns the information shown in Table 8-5.

Table 8-5 DBGetErr Information
Parameter Information
err1 TP Desktop Connector DDEV status value (--4000 range)
err2 ACMS system status value (--3000 range), status value from the communications toolbox in use by the session (--1 or 0 through 11), or other status values
item1 Symbol name for the status value returned in the err1 parameter
item2 Symbol name for the status value returned in the err2 parameter
errorMsg Symbol name for the status returned on the original TP Desktop Connector client service call

Using information returned in the DBGetErr parameters, the desktop client program can decide how to handle the error condition. Depending on the error, the condition is possibly recoverable. For example, if the return status from the DBState service indicates that a requested task cannot be accessed for security reasons (ACMSDI_SECCHK is returned in the err2 parameter), the desktop client program can simply report the error to the user and allow another task selection without signing the user out of the ACMS system.

Many errors returned on TP Desktop Connector client services are not recoverable. If an unrecoverable error is specific to a particular sign-in, the desktop client program can simply terminate the session and continue processing for other sessions. If the error is more severe, the desktop client program can report the problem to the user, terminate all active sessions, and exit. Example 8-14 shows example code calling the DBGetErr service.

Example 8-14 Calling DBGetErr

/* 
 *  EXIT PROCEDURE - Call DBGetErr to see what happened 
 */ 
my_exit (short status, long sessid1, char *msg ) 
{ 
    static long int error1;           /* Error Declarations for DBGetErr */ 
    static long int error2; 
    static char     item1[255]; 
    static char     item2[255]; 
    static char     errorMsg[255]; 
    static long int error_status; 
    
    printf ("\n Returned Status code is %d, Message is %s\n", status, msg ); 
    
    if (sessid1) 
    { 
    
    error_status = DBGetErr(sessid1,&error1,&error2,&item1,&item2,&errorMsg,NULL); 
    if (error_status != noErr) 
           printf (" DBGetErr error code is %d\n", error_status); 
    else 
    { 
      printf(" Primary Error Message is %s\n",&errorMsg[1]); 
      printf(" Error Message one is %s\n",&item1[1]); 
      printf(" Error Message two is %s\n",&item2[1]); 
      printf(" Status code one is %d, Status code two is %d\n", error1, error2); 
    } 
    
           status = DBEnd (sessid1, NULL); 
           if (status != noErr) 
                   printf (" DBEnd error code is %d\n", status); 
 
           printf( "\n" ); 
 
    } 
    
    exit (0); 
} 

Because the DBGetErr service requires a valid session identification as a parameter, errors returned on the DBInit service require special handling. If an error occurs on a DBInit call, a session is established but no connection to the ACMS system is established. In most cases, a session identification and the bad return status are passed back to the desktop client program. The desktop client program should handle all errors on DBInit; if the desktop client program receives a bad return status and a session identification on the DBInit call, it must provide special handling for this session, known as a zombie session. The zombie session associated with this session identification differs from a normal session in the following ways:

A zombie session counts toward the maximum number of sessions supported by the TP Desktop Connector DDEV. Use the DBEnd service to remove a zombie session from the desktop system.

Two error conditions can cause a zero session identification to be returned on the DBInit service. These two error conditions are:

If a zero session identification is returned, no zombie session is allocated and no additional error information can be obtained by calling DBGetErr.

The DBGetErr service is called by the ACMSGetErr XFCN. Example 8-15 shows the call to the ACMSGetErr XFCN.

Note

Some characters that can print only in a Macintosh environment are deleted from this example. Check the file supplied with TP Desktop Connector for the precise format.

Example 8-15 Calling ACMSGetErr

function GetErr currentsession, cstring 
  global gerr1, gerr2, gitem1, gitem2, gmsg 
  global itemtext1,itemtext2,msgtext,errorfile,avertzlogfile 
  
  put 0 into got1 
  put 0 into got2 
  put bg fld "error" into "gerr1" 
  put ACMSGetErr (currentsession,"gerr1","gerr2","gitem1","gitem2", 
  "gmsg")  into status 
  if status <> 0 then 
    return status 
  end if 
  
  open file errorfile 
  
  repeat forever 
    read from file errorfile until return 
    if it is empty then 
      write "Error not found" &return to file avertzlogfile 
      exit repeat 
    else 
      if it is return then 
        next repeat 
      end if 
      if item 1 of it = gerr1 then 
        put item 2 of it into errtext1 
        put 1 into got1 
        if got2 = 1 then 
          exit repeat 
        end if 
      end if 
      if item 1 of it = gerr2 then 
        put item 2 of it into errtext2 
        put 1 into got2 
        if got1 = 1 then 
          exit repeat 
        end if 
      end if 
    end if 
  end repeat 
  close file errorfile 
  if got1 <> 0 and got2 <> 0 then 
    write  "Error in "&cstring&" = "&errtext1&","&errtext2 
    &gitem1&gitem2&gmsg 
    &" for session"&currentsession&return to file avertzlogfile 
  end if 
  if got1 <> 0 and got2 = 0 then 
    write  "Error in "&cstring&" = "&errtext1Â 
    &" for session"&currentsession&return to file avertzlogfile 
  end if 
  if got2 <> 0 and got1 = 0 then 
    write  "Error in "&cstring&" = "&errtext2Â 
    &" for session"&currentsession&return to file avertzlogfile 
  end if 
  if got1 = 0 and got2 = 0 then 
    write "Error in "&cstring&" = "&gerr1&","&gerr2&" - text not found" 
    &" for session"&currentsession&return to file avertzlogfile 
  end if 
  return status 
end GetErr 

8.2.7 Canceling Active Tasks on the Macintosh System

You can cancel an active task on a Macintosh system with the DBBreak client service. You cannot use DBBreak while processing and exchange step request. If you call cancel while processing an exchange step request, TP Desktop Connector returns "ACMSDI_EXCHACTV" in DBGetErr. If you issue a cancel when another cancel is already in progress, TP Desktop Connector returns the message "ACMSDI_CANCELACTV".

If you issue a DBGetErr right after a DBBreak, you receive the status of the DBBreak, and not the task call. Issue the client services in the following sequence to receive the anticipated result:

If you are using HyperCard or 4th Dimension, you must write your own externals to cancel a session.

Note

Because of limitations in the MacTCP transport, you cannot use DBBreak with this transport.

8.2.8 Deleting Orphaned Sessions

TP Desktop Connector provides two programs on the Macintosh system to delete an orphaned session, a session that remains active even though the application that created it has terminated. Orphaned sessions usually occur during application development, when an application aborts for various reasons leaving the session attached on the gateway end. The two programs are:

Note

1 DBState and DBGetItem are exceptions; they do not return the NoErr status.

8.3 Exchange Step Support and Other Advanced Features

This section describes how to implement exchange steps in the TP Desktop Connector Macintosh client using the DAM application programming interface (API).

8.3.1 DAM Constraints

The DAM API assumes a strict client/server model wherein the desktop device always acts as the client requesting services of the back-end gateway. Sign In, Sign Out and CallTask are three services implemented with DAM using its client/server model. However, exchange steps change this model, reversing the roles of client and server. Thus, after a task is initiated, instead of receiving a response to the CallTask Request in the form of a CallTask Response (End Task) from the back end, the client can receive, instead, a request for services in the form of an exchange step.

The TP Desktop Connector portable API recognizes this reversal of roles by implementing special presentation procedures wherein the application running on the desktop device can play its role of gateway:

The DAM API does not allow for the implementation of presentation procedure callbacks. Therefore, every transmission from the back end must be treated as if it were a response to the previous transmission from the desktop. Thus, a CallTask Request from the desktop can receive any of the following responses:

The back end can send any of these responses (four of which are actually requests) in response to any transmission from the desktop. The desktop, however, must reply to each of these responses as shown in Table 8-6.

Table 8-6 Desktop Constrained Transmissions
Transmission from the Back End Required Transmission from the Desktop
CallTask response None allowed
Send request Send response
Receive request Receive response
Transceive request Transceive response
TDMS request TDMS response

During the processing of exchange steps, the desktop becomes the gateway, and must respond with predefined message types to the back-end requests. The DDEV can do very little to assure that the proper responses are received from the back end, except to assure that:

8.3.2 Message Types

From the client application perspective, six message types are related to calling a task. Each message is a two-way message: request and response. See Table 8-7.

Table 8-7 Message Types
Message Type Requestor Respondent
CallTask Desktop Back end
Enable Back end Desktop
Send Back end Desktop
Receive Back end Desktop
Transceive Back end Desktop
TDMS Back end Desktop

The application identifies the message types using keywords.

Table 8-8 shows the keywords and corresponding message types.

Table 8-8 Keywords
Keyword Message Type
CALLTASK CallTask request/response
ENABLE Enable request/response
SEND Send request/response
RECEIVE Receive request/response
TRANSCEIVE Transceive request/response
TDMS TDMS request/response

8.3.3 Keyword Acquisition

The desktop application program can both send all keywords to the DDEV and acquire all keywords from the DDEV. The CALLTASK keyword, when acquired, identifies a CallTask Response message (End Task) from the back end. When sent, CALLTASK identifies a CallTask Request message (Start Task). All the other keywords are associated with exchange steps and identify a request from the back end when acquired, and a response from the desktop when sent.

The following sections discuss how to send and acquire keywords.

8.3.3.1 CALLTASK

CALLTASK is passed to the DDEV by the first of a series of prescribed DBSend or DBSendItem calls, which collectively pass all required parameters for task initiation. You do not need to acquire the CALLTASK keyword from the DDEV. If an application program knows that it is dealing with a NO I/O task, you can immediately issue DBGetItems to get workspace data. However, you can acquire the CALLTASK keyword from the DDEV, if necessary. See Section 8.3.3.3 for the method to acquire the CALLTASK keyword.

8.3.3.2 Keywords that Identify Messages Sent from the Back End

All keywords other than CALLTASK identify request messages from the back end. When a desktop application program does not know what kind of message it may be receiving from the back end, it needs to acquire the message's keyword from the DDEV. See Section 8.3.3.3 for the method to acquire a message's keyword.

8.3.3.3 Keyword Acquisition Using DBGetItem

After sending a message to the back end with DBExec, the application program issues a series of DBState calls until a status code other than rcDBExec is returned. The status code rcDBExec indicates that the transaction is executing on the back end. The two successful return statuses from DBState are:

In this context, data means workspaces with data.

When the application receives an rcDBNull or rcDBValue status, it knows it has received an error-free message from the back end. For NO I/O tasks (no exchange steps), the only message type it can receive is CallTask Response. However, with exchange steps, the application might not know what type of message has arrived.

To determine the type of message, the application issues a DBGetItem call to the DDEV to acquire the keyword. The DBGetItem has a special data type associated with it to identify the fact that it is meant to acquire a nonworkspace data item; that is, a data item that is not part of a workspace, such as the keyword. Nonworkspace data items are sometimes referred to as the message's header data.

Example 8-16 (written in C) shows how to issue a DBGetItem to acquire the message's keyword.

Example 8-16 Acquiring a Keyword with DBGetItem

/* 
** ELEMENTS DEFINED IN acmsdi_mac.h 
*/ 
#define maxKWsize 10            /* maximum keyword size */ 
#define typeHdrItem 'hdit'      /* message header item data type */ 
 
/* 
** PROGRAM CODE FOLLOWS 
*/ 
unsigned short keyword_len;                /* keyword length */ 
DBType dataType;                           /* data type for DBGetItem */ 
char keyword[maxKWsize];                   /* keyword */ 
   .
   .
   .
dataType = typeHdrItem;           /* data type is message header item */ 
keyword_len = maxKWsize;          /* keyword field size */ 
 
status = DBGetItem (sessID,       /* session ID */ 
          NULL, 
          &dataType,              /* -> data type */ 
          (short *) &keyword_len, /* -> length of longest keyword */ 
          NULL, 
          NULL, 
          keyword,                /* -> where keyword to be returned */ 
          NULL); 

In Example 8-16, all arguments except session identifier are passed by reference, because they are potentially modifiable by the DDEV. This DDEV (acmsdi), however, does not modify the data type field.

Nonworkspace data items are discussed in Section 8.3.4. The first nonworkspace data item in every logical message type is its keyword, and Example 8-16 illustrates how to obtain it. However, there is no requirement that the keyword be obtained. If you know what message type has been returned, you can start issuing DBGetItems with no data type specified to obtain workspace data.

8.3.4 Nonworkspace Data Items

Nonworkspace data items are data items that are not part of a workspace. For example, for a CallTask Request (Start Task), you must provide the task name and the application name. These parameters are not part of any workspace but are inserted into the header portion of the message. All messages have some kind of nonworkspace data that needs to be sent to the DDEV or, in some cases, acquired from the DDEV.

Figure 8-4 illustrates nonworkspace data.

Figure 8-4 Nonworkspace Data


8.3.4.1 Sending Nonworkspace Data

A CallTask Request message has the following nonworkspace data items that must be sent from the application to the DDEV:

The four nonworkspace data items plus the keyword, to identify the message type, are sent to the DDEV by five prescribed DBSend or DBSendItem calls. This method is not restricted to CallTask Request messages. The nonworkspace data associated with the Enable, Send, Receive, Transceive, and TDMS Response messages must be sent to the DDEV in a series of DBSend or DBSendItem calls. The general rule is that you must send the keyword first, followed by each of the required nonworkspace data items in a prescribed order.

The Table 8-9 shows the items that must be sent with each message type and the prescribed order in which they must be sent.

Table 8-9 Messages Sent to the Back End
Message Items
CallTask request Keyword (CALLTASK)
Task name
Application name
Selection string
Number of workspaces
Enable response Keyword (ENABLE)
Desktop status
Forms session ID
Send response Keyword (SEND)
Desktop status
Receive control text
Receive control text count
Receive response Keyword (RECEIVE)
Desktop status
Receive control text
Receive control text count
Number of workspaces
Transceive response Keyword (TRANSCEIVE)
Desktop status
Receive control text
Receive control text count
Number of workspaces
TDMS response Keyword (TDMS)
Desktop status
Number of workspaces


Previous Next Contents Index