Tivoli Service Desk 6.0 Developer's Toolkit Interface Designer Guide

Chapter 7: Using CPIC

Back to Table of Contents


Introduction

Overview

The Common Programming Interface for Communications (CPIC) provides a consistent API for applications that require application-to-application communication. The CPIC interface makes use of SNA's LU 6.2 to create a set of interapplication services, including:

CPIC commands are built into the TSD Script language to extend these services to the TSD Script programmer. CPIC was chosen over the base APPC macros to ensure consistency across platforms.

This section of the book is intended as a guide to TSD Script programmers using CPIC to build TPs. For detailed information on SAA CPIC programming, refer to the IBM manual, Systems Application Architecture Common Programming Interface for Communications Reference, SC26-4399.

CPIC must be installed for any CPIC commands to work. If CPIC is not installed correctly, the use of CPIC commands causes Tivoli Service Desk (TSD) Developer's Toolkit to display an error message indicating that CPIC could not be loaded.

Terms & Concepts

APPC

APPC is advanced peer-to-peer communication.

Basic conversation

Basic conversation is a conversation type in which applications exchange data in a standard byte stream format. This format contains two-byte length fields (called LLs) which specify the length of the buffer to follow. Each grouping of LL data is called a logical record.

Conversation

A conversation is the logical connection between two applications using CPIC or APPC to exchange data. There are two types of conversation, mapped, and basic. A conversation connects applications using a session. A CPIC application may converse with an APPC application in the same manner that it converses with another CPIC application.

DDF

A DDF (Data Description File) is a file that is used to map the relationship between TSD Script record structures and transmitted byte buffers.

LU

A LU (Logical Unit) is, effectively, a virtual machine. While you may designate each physical machine as a LU, it is also possible to configure multiple LUs in one physical machine. Note that CPIC uses only LU Type 6.2 nodes.

Mapped conversation

A mapped conversation is a conversation type that allows partners to exchange arbitrary data records in pre-determined formats.

Mode name

A mode names is used by APPC to designate the properties for the session between the LUs during a conversation. These properties include the class of service.

Node service

A node service is a application (or set of applications) that provides basic utility functions for an LU. Services provided include manipulation of side information, application start-up processing, and application-termination processing. OS/2's node services are provided by Communications Manager (CM) or Communications Manager/2 (CM/2).

Partners

Partners are two CPIC applications that exchange data over CPIC conversations.

CPIC conversations can be full duplex. This means that at any given period during a CPIC conversation, one partner has permission to send and the other partner is in receive state (meaning it is ready to receive the data). A application that is in receive state can issue a request to send when it needs to send data. The partner is notified of this request, and the requesting application receives notification in the StatusReceived parameter.

SDN

SDN (Symbolic Destination Name) is a CPIC configuration name in Communications Manager/2 that allows a application to indicate a set of attributes to be used for a conversation allocation request.

Session

A session is a logical connection between two LUs. LUs communicate through sessions.

Side information

Initialization information used by CPIC during an attempt to establish a conversation. Side information includes the partner LU name, mode name, and TP name. This information is configured in advance of the conversation.

Note: Side information is referenced by an SDN.

SNA network

An SNA network is a logical network of LUs.

Sync level

Sync level indicates the degree of synchronization a CPIC conversation uses. The sync level can be one of the following:

SYNC_POINT

SYNC_POINT indicates that your application supports full SAA Resource Recovery operations, such as Take Commit and Take Backout notifications.

Note: SYNC_POINT is not supported in OS/2.

TP

TP (Transaction Program) is an application that uses CPIC or APPC commands to participate in a conversation.

TP name

The TP name is the name of a transaction application. This name is specified in side information. Depending on the operating system, the TP name may specify a table entry for the target LU's node services application. This table is used to look up the information needed to start the TP.

Starting a Conversation with Another Program

A simple conversation example

Following is a short example of the method used when an application starts a conversation with another application.

  1. Program A issues a CPICInitialize command to prepare to start the conversation. It gives an SDN to designate Program C as the target of the conversation. Program A receives a unique identifier for the conversation.
  2. Program A issues a CPICAllocate command using the conversation identifier.
  3. Via node services, CPIC tells the partner LU (specified in the side information used in step 1) that Program C should be started to accept the new conversation.
    Result: Program C starts and issues the CPICAccept command. It receives a conversation identifier for use in further CPIC commands that are exchanged during the conversation.

TSD Script Data Description Files

Overview

TSD Script does not allow direct control of the allocated size of memory structures, which frees programmers from having to worry about the size of the records they declare.

Although this is considered an attractive attribute of a fourth generation language, it can present difficulties in working with CPIC applications. CPIC applications send and receive byte buffers of a specific size and format. A partner application may use different storage formats than the local application, including non-Intel integers and EBCDIC character strings.

Data description files (or DDFs) address the possibilities of different buffer sizes. A DDF defines the exact form of a transmitted byte buffer and specifies format translation/conversion. TSD Developer's Toolkit uses these DDFs as "filters" for both outgoing and incoming buffers to a CPIC application.

The basic structure of a DDF is:

-- Double dashes are comment to end of line.
-- The first section is the partner section.
*PARTNER
-- character conversion types
EBCDIC=TRUE
-- integer byte order
NON_INTEL=TRUE
-- character conversion table. If not specified, TSD Developer's
Toolkit will
-- use the CM/2 AE table. This default table
-- may be insufficient for your use (for example, it
-- converts embedded spaces to x'00'). If you want a
-- more normal conversion table, set the CM/2 translation
-- table file name to ACSGTAB.DAT, which is provided with
-- CM/2. Then set CUSTOM_CONVERT to TRUE.
CUSTOM_CONVERT=TRUE
-- This section is the field section. It is used
-- to describe each field of the record and its byte
-- mapping and translation. Essentially, this section
-- shows how the data buffer should look just after it
-- is received (before conversion), or just before a
-- send (after conversion).
*FIELDS
-- Fieldname Type ByteWidth SendUnknowns? Default
   name CHAR 20 FALSE
   street CHAR 20 TRUE
   age INTEGER 20 TRUE
   birthDate CCYYMMDD 8 FALSE

In this example, the partner application runs on an EBCDIC machine with non-Intel style integers (such as an IBM System 370). The record that is sent is declared in TSD Script like this:

SomeRecordName IS RECORD
   name :STRING;
   street :STRING;
   age :INTEGER;
   birthDate :DATE;
   description:STRING;
END;

The description field is not included in the DDF, which means that the description field is not transferred during CPIC communications.

The Partner section

This section of a DDF describes the partner application's machine type. The beginning of this section is marked by the text *PARTNER. The partner section indicates the types of data conversions that TSD Developer's Toolkit performs. For instance, setting EBCDIC=TRUE means that TSD Developer's Toolkit converts all character strings to and from EBCDIC when communicating with the partner application.

Partner attributes

In the Partner section, the following attributes should be set. Any attributes you do not set take the indicated default value.

The Fields section

This DDF section specifies fields and the field types to be packed or unpacked in CPIC data buffers. This section in the DDF begins with the line containing "*FIELDS". Each line in the Fields section applies to one TSD Script transferred record field. The format of such a line is as follows:

{fieldname} {fieldtype} {bytewidth} {sendunknowns?} {default}

White space divides each column; the column definitions are listed here:

The $INCLUDE command

The $INCLUDE command simplifies the organization of a DDF. This command provides the ability to "link" other files dynamically. When TSD Developer's Toolkit encounters the $INCLUDE command, it loads the specified DDF and places its field definitions in the current DDF.

The $INCLUDE command can be included anywhere in the Fields section. The format of the $INCLUDE command is:

$INCLUDE({DDFname})

If the file is not in the current directory, TSD Developer's Toolkit searches the DPATH for the file. If it is not found, then TSD Developer's Toolkit returns an error.

The $SIZEOF command

The $SIZEOF command automatically recalculates the size of the included files Included files do not have to be manually recounted if another field is added to them.

The $SIZEOF and $INCLUDE commands are used in special cases, like setting up a vectored buffer. They can be used in combination like this:

*PARTNER
   EBCDIC =TRUE
   NON_INTEL =TRUE
   CUSTOM_CONVERT =TRUE
*FIELDS
GDS1310 INT 2 TRUE 4880
GDS1311LEN INT 2 TRUE
   $SIZEOF(1311.DDF) + 2 $INCLUDE(1311.DDF)
GDS1549LEN INT 2 TRUE
   $SIZEOF(1549.DDF) + 2 $INCLUDE(1549.DDF)
DataLen INT 2 TRUE
   $SIZEOF(RTRNDATA.DDF) + 2 $INCLUDE(RTRNDATA.DDF)

DDF field types

The types recognized for DDF processing are:

Using CPIC with Communications Manager/2

Overview

There are several details you should know before you attempt to write an OS/2 CPIC application. Some of these can be grouped by the type of node services you have on your system.

Incoming allocations

Because of the way node services set a TP to receive an incoming allocation, an OS/2 CPIC application cannot be an SNA Service TP. Review the following steps that summarize how an incoming allocation is handled:

  1. Node services starts a process and sets an environment variable named APPCTPN to be equal to the TP name.
  2. When the application issues an Accept command, node services checks the APPCTPN of the accepting application's environment.
  3. Node services scans the list of waiting incoming allocations for one with the same TP name.
  4. If the name is found, node services completes the call. Because SNA service TP names start with a hexadecimal number, they cannot be set in an OS/2 environment variable.

Multiple TSD Script applications with TPs

If you have more than one TSD Script application for which you want to set up a TP, you have to do a special set up. Communications Manager/2 only allows you to specify kml.exe as the OS/2 application PATH and file for one TP definition. For the other one, create an OS/2 command file containing the following commands:

SET APPCTPN={your TP name}
START /C KML /U{path to your KB} {your KB name}
EXIT

Communications Manager/2 Version 1.1 (CM/2)

Communications Manager/2 allows a single CPIC process to accept multiple conversations. Additionally, a CPIC application may issue one Initialize command, as long as no prior Accept commands have been issued.

TSD Script CPIC Case Study

Overview

This section is a brief case study of the process for creating a simple CPIC application. The application is designed to complete a file transfer.

To illustrate the benefits of CPIC, the case study has two example modules. The application is created in the first example module. In the second example module, some minor changes have been made to the application to improve performance.

Assumptions

This case study makes several assumptions about your familiarity with CPIC, Communications Manager/2, and communications processing in general. For example, it is assumed that you are familiar with the Communications Manager/2 CMSETUP utility.

The partner application (RCV.CMD)

To begin, review the partner application that is written in REXX.

The REXX partner application is named RCV.CMD. Essentially, this application receives data (storing it in a stem variable) until the status received parameter indicates that the application may now send data.

Following this code example are explanations that provide additional details about the application.

/* RCV.CMD */ 
/* Receives data strings, building a buffer of all data. /*Upon completion of*/
/* receiving, sends back the buffer. */ 
/* CPIC commands used: CMACCP */ 
/*                     CMCFMD */ 
/*                     CMDEAL */ 
/*                     CMRCV */ 
/*                     CMSEND */ 
/* a few useful constants */ 
CM_OK               = 0 
/* status received */ 
CM_SEND_RECEIVED    = 1 
CM_CONFIRM_RECEIVED = 2 
/* data received */ 
CM_NO_DATA_RECEIVED = 0
MaxLength           = 257; 
BufferLen           = 0; 
FileBuffer.0        = 0; 
'CPICREXX' 
address cpicomm 
'CMACCP Conv_ID RetC'; 
if \(RetC = CM_OK) then do 
     SAY 'ACCP = 'Retc 
end; 
'CMRCV Conv_ID Data MaxLength DataReceived 
ReceivedLength StatusRecvd ReqToSendRecvd Retc'; 
if \(RetC = CM_OK) then do 
     SAY 'RCV = 'Retc 
end; 
do while (RetC = CM_OK) & 
  (StatusRecvd \= CM_SEND_RECEIVED) 
  if (DataReceived \= CM_NO_DATA_RECEIVED) then do 
/*    SAY Data */ 
      FileBuffer.0 = FileBuffer.0 + 1; 
      i = FileBuffer.0; 
      FileBuffer.i = Data; 
   end; 
   if (StatusRecvd = CM_CONFIRM_RECEIVED) then do 
      'CMCFMD Conv_ID RetC'; 
   end; 
   'CMRCV Conv_ID Data MaxLength DataReceived 
    ReceivedLength StatusRecvd ReqToSendRecvd Retc'; 
   if (RetC \= CM_OK) then do 
      SAY 'RCV = 'Retc 
   end; 
end; 
SAY 'Re-transmitting file' 
DO i = 1 TO FileBuffer.0 
   BufferLen = LENGTH(FileBuffer.i); 
   Data = FileBuffer.i; 
   'CMSEND Conv_ID Data BufferLen ReqToSendRecvd RetC'; 
   if (RetC \= CM_OK) then do 
      SAY 'SND = 'Retc 
   end; 
END; 
'CMDEAL Conv_ID RetC'; 
address cmd 
'EXIT'

Example module 1 - FILESND.KB

The goal of this application is to read a text file and to transmit each line to a partner application. After the application completes the file transfer, it begins receiving the same file back again and displays each line in a display window.

  1. Parse the file with the command KP FILESND.
  2. Start the CMSETUP application from the CM/2 folder.
    Result: The CPI Communications Manager Configuration Utility dialog box appears.
  3. Type the name FILESND in the box.
  4. From the CPI Communications menu, choose SNA Features.
    Result: The CM/2 Configuration Definition dialog box appears.
  5. Set up the side information entry.
  6. In the SNA Features dialog box, choose the CPI Communications Side Information item.
  7. Choose Create.
  8. Type the following into the dialog box:
    SDN = FILESND
    Target LU = {target machine name here}
    TP Name = FILERCV
    Security = NONE
    Mode = #INTER
  9. Choose OK.
  10. Select the Transaction Program Definitions item
  11. Choose Create.
  12. Type these values in the dialog box:
    Service TP = deselected
    TP Name = FILERCV
    OS/2 Program PATH and Filename = CMD.EXE
    Conversation security required = deselected
    Program Parameters = /C {PATH to tutorial code}RCV.CMD
  13. Choose Continue.
  14. Type the following:
    Presentation Type = Background
    Operation Type = Queued, Attach Manager started

Review of setup procedure

Beginning with Step 3, you set up an entry into Communication Manager/2's Side Information Table. The Side Information Table is used during initialization of a conversation. Initialization occurs as follows:

  1. An application calls CPICInitialize, passing an SDN as a parameter. An SDN acts as a key to the Side Information Table.
  2. CPIC uses the SDN to set attributes for the new conversation. The attributes can represent the target machine and TP.

Using this method, CPIC applications can be written that have no hard-coded, site-specific information. It also provides a standard method for all CPIC applications to access this type of information.

Beginning with Step 8, a TP definition is created. This entry tells node services how to start a certain TP.

When a conversation is allocated, the LU that requested the allocation sends the desired TP name to the target LU node services system. The node services system checks to see if that TP name is defined on the system. If it is defined, the node services follow the instructions on how to start the TP. If it can successfully start the application, it does (when Attach Manager started is set for the TP). The TP then issues a CPICAccept. The requesting LU gets a success indication and the conversation is started.

For this REXX application, an OS/2 command processor starts (CMD.EXE). The parameter string tells CMD.EXE to exit when the command is completed (/C) and what command to run (RCV.CMD).

Starting the RCV.CMD file from the command line

The next part of the case study starts the RCV.CMD file from the OS/2 command line.

  1. Set an indicator to tell CM/2 which TP is waiting for a incoming conversation. This is done be setting an environment variable for the command session:

    SET APPCTPN=FILERCV

    (Optional) To avoid an infinite wait for an incoming allocation, you can edit your Node Definition File (NDF) in the CMLIB directory. This file has the same name as the Communications Manager/2 configuration file.
  2. Find the section defining the attributes for the FILERCV TP (search for FILERCV).
  3. Change the INCOMING_ALLOCATE_TIMEOUT and the RECEIVE_ALLOCATE_TIMEOUT to positive integers (the units are in seconds-180 for each is a good benchmark).
  4. Save the file.
  5. To make these changes take effect, start the CM Setup utility and make enough changes to data fields to cause CM Setup to re-verify and apply the changes dynamically.
  6. Run the REXX application by typing RCV and pressing ENTER.
    Result: The application pauses until either an allocation arrives, or the timeout for RECEIVE_ALLOCATE_TIMEOUT is surpassed. Upon completion, this application exits the current command process.
    Note: Do not start the REXX application until you are ready to start FILESND.KB.

Run FILESND.KB

This transmits the source file back and forth between the two applications, and then displays the results in a window.

It may take a little time for the double transfer to finish. Below the file listing in the window, you see the timing results.

Additionally, notice the line number for each line of the file. These numbers were transmitted back and forth with each line of the text file.

FILESND.KB line listing

Following this section of numbered lines is a discussion about the file.

1
2      KNOWLEDGEBASE FILESND;
3
4      ROUTINES 
5      PROCEDURE DoConversation(VAL Args:List of String);
6                              (* sdn, infile *) 
7
8
9      PRIVATE 
10
11     CONSTANTS 
12        CPIC_SUCCESS IS 1; 
13
14     TYPES 
15        FileRec IS RECORD 
16           LineNbr:Integer; 
17           Buff:String; 
18        END; 
19
20     ROUTINES 
21
22     FUNCTION RcvData(REF w:WINDOW, VAL 
                        Conv:Conversation) 
                        :INTEGER IS 
23     VARIABLES 
24        totalBuff :FileRec; 
25        dataRcvd  :integer; 
26        statRcvd  :integer; 
27        reqTSRcvd :integer; 
28        rc        :integer; 
29     ACTIONS 
30        IF (not(Known(w))) THEN 
31        WinCreateScrollWindow($DESKTOP,w, 
32                              $NullHandler, 
                                1,1,67,7, 
                                'FileSnd','', 0, 
                                $WinBorder+ 
                                $WinTitle+ 
                                $WinHScroll+ 
                                $WinVScroll+ 
                                $WinSysMenu+ 
                                $WinResize); 
          END; 
33       REPEAT 
34       rc := CPICReceive(Conv,'FILEREC.DDF', 
                           totalBuff,DataRcvd, 
                           StatRcvd,ReqTSRcvd); 
35          IF (rc > 0) THEN 
36          IF ((StatRcvd = $CPICConfirmReceived) or 
37             (StatRcvd = $CPICConfirmSend 
                Received)) THEN 
38              rc := CPICConfirmed(Conv); 
39        END; 
40            totalBuff.buff := StrTrim 
                                (totalBuff.buff); 
41             WinWriteLn(w,totalBuff.lineNbr:5&' 
                         :'&totalBuff.buff); 
42        END; 
43       UNTIL ((rc <> 1) OR ((StatRcvd = 
                            $CPICSendReceived) OR 
44                  (StatRcvd = $CPICConfirmSend 
                     Received))); 
45       Exit(rc); 
46    END; -- RcvData
47
48
49 --------------------------------------------- 
50 -- Description: Reads in the specified file, 
      transmitting each line via CPIC 
51 -- to the partner specified through the 
      given SDN. 
52 --------------------------------------------- 
53 PROCEDURE DoConversation(VAL Args:List of 
                            String) IS 
54 VARIABLES 
55    Conv     :Conversation; 
56    fRec     :FileRec; 
57    ReqTSRcvd:INTEGER; 
58    rc       :INTEGER; 
59    inf      :FILE; 
60    w        :WINDOW; 
61    t1,t2    :TIME; 
62 ACTIONS 
63    t1       := $NOW; 
64    IF (ListLength(Args) <2) THEN WinMessageBox($DESKTOP,ҏopsҬ $MBOK,ҋML FILESND {SDN} {INFILE}ҩ; Exit; END; FOpen(inf,Args[2],$Read); rc :="CPICInitialize(Conv,Args[1]);" IF (rc <CPIC_SUCCESS) THEN WinMessageBox($DESKTOP, ҃PIC ErrorҬ$MBOK, ҉nit returns Ѧrc); Exit; END; rc :="CPICSetSyncLevel(Conv," $CPICNone); IF (rc <CPIC_SUCCESS) THEN WinMessageBox($DESKTOP, ҃PIC ErrorҬ$MBOK, ғSL returns Ѧrc); END; rc :="CPICAllocate(Conv);" IF (rc < CPIC_SUCCESS) THEN WinMessageBox($DESKTOP, ҃PIC ErrorҬ$MBOK, ҁllc returns Ѧrc); Exit; END; rc :="CPICSetPrepareToReceiveType" (Conv, $CPICPrepToReceiveFlush); IF (rc < CPIC_SUCCESS) THEN WinMessageBox($DESKTOP, ҃PIC ErrorҬ$MBOK, ғPTR returns Ѧrc); END; fRec.lineNbr :="0;" while (FReadLn(inf,fRec.Buff)> <2) THEN
65    WinMessageBox($DESKTOP,'Oops',
                    $MBOK,'KML FILESND {SDN}
                   {INFILE}');
66       Exit;
67    END;
68
69    FOpen(inf,Args[2],$Read);
70
71    rc := CPICInitialize(Conv,Args[1]);
72    IF (rc < CPIC_SUCCESS) THEN
73       WinMessageBox($DESKTOP,
                      'CPIC Error',$MBOK,
                      'Init returns '&rc);
74       Exit;
75    END;
76    rc := CPICSetSyncLevel(Conv, $CPICNone);
77    IF (rc < CPIC_SUCCESS) THEN
78       WinMessageBox($DESKTOP,
                      'CPIC Error',$MBOK,
                      'SSL returns '&rc);
79    END;
80    rc := CPICAllocate(Conv);
81    IF (rc < CPIC_SUCCESS) THEN
82       WinMessageBox($DESKTOP,
                      'CPIC Error',$MBOK,
                      'Allc returns '&rc);
83       Exit;
84    END; 
85
86    rc := CPICSetPrepareToReceiveType
               (Conv, $CPICPrepToReceiveFlush); 
87    IF (rc < CPIC_SUCCESS) THEN
88       WinMessageBox($DESKTOP,
                      'CPIC Error',$MBOK,
                      'SPTR returns '&rc);
89    END;
90
91    fRec.lineNbr := 0;
92    while (FReadLn(inf,fRec.Buff) > 0) do
93         fRec.Buff := fRec.Buff & Char(13) & 
           Char(10);
      -- add CR LF
94      fRec.lineNbr := fRec.lineNbr + 1;
95      rc := CPICSend(Conv,
                      'FILEREC.DDF',
                      fRec,
                      ReqTSRcvd);
96      IF (rc < CPIC_SUCCESS) THEN
97         WinMessageBox($DESKTOP,
                        'CPIC Error',$MBOK,
                        'Send returns '&rc);
98         ExitLoop;
99         END;
100        CPICFlush(Conv);
101     END;
102     FClose(inf); 
103
104     IF (rc = CPIC_SUCCESS) THEN
105        CPICPrepareToReceive(Conv);
            -- Indicates Partner may send now.
106        t2 := $NOW;
107        RcvData(w,Conv);
108     END; 
109
110     CPICDeallocate(Conv);
111     WinWriteLn(w,'<<<<<<<<<<<<<<<<<<<<<<<<
                      >>>>>>>>>>>>>>>>>>');
112     WinWriteLn(w,'Elapsed time for outgoing
                   transmission: '&
113                TimeDif(t2,t1,$SECONDS)&'
                           seconds');
114     WinWait(w);
115  END;
116
117

Program review

Following is a review that explains the preceding code sample.

Line 42 contains some vestige code. This application was originally written to use the sync level of $CPICConfirm, and RcvData had to detect and acknowledge any confirms by the partner. Since the sync level is set to $CPICNone in line 80, this does not happen.

Lines 75-93 contain the conversation setup commands. $CPICNone is the default for a conversation, so does not need to be set.

In line 90, after the CPICAllocate, the prepare to receive type is set. This indicates the type of action to be taken whenever CPICPrepareToReceive is called. Flush was chosen so that the last buffer is transmitted as soon as data is ready for receipt.

File transmission is accomplished in lines 96-105. Notice that this occurs with only two CPIC commands (CPICSend and CPICFlush). A record, defined in lines 15-17, is sent.

The map file FILEREC.DDF looks like:

1
2    *PARTNER 
3       EBCDIC = FALSE 
4       NON_INTEL = FALSE 
5       CUSTOM_CONVERT = TRUE 
6
7    *FIELDS 
8    LineNbr INTEGER 2 TRUE 
9    Buff ASE_STRING VAR TRUE 
10

Both the line number and the line contents are transmitted to the partner application. Because the REXX application treats the buffer as one string, the buffer can be sent back, and TSD Developer's Toolkit can once again extract the two fields.

Line 104 is where the buffer flushes. This causes the data passed to CPICSend to be transmitted to the partner immediately.

After transmitting the file, the partner is notified that it may begin sending data. The RcvData function (line 22) handles the incoming data.

RcvData receives incoming FILEREC data until either there is an error (including the partner deallocating the conversation) or the application again receives the send notification.

The conversation is deallocated in line 114.

Example module 2 - FILESND2.KB

This is the second example module. The goal of this application is the same as the first example. The difference between the two is that some of the code was changed to gain performance.

You can use the same SDN for FILESND2 as you did for FILESND.

Running FILESND2

  1. Parse FILESND2.
  2. At the command line, type:
    KML FILESND2 FILESND {filename}
  3. After the application runs, look at the elapsed time at the end of the listing. It should be faster than example module 1.

File line listing

Here is a listing of FILESND2.KB:

1
2     -- A little more efficient example.
3     -- Note that certain lines have been
         commented out. These were vestiges 
4     -- from the original FILESND.KB. New lines
          are marked by (* NEW *).
5
6     KNOWLEDGEBASE FILESND2;
7 
8     ROUTINES
9        PROCEDURE DoConversation(VAL Args:
                                  List of String);
10      (* sdn, infile *)
11
12
13    PRIVATE 
14
15    CONSTANTS
16       CPIC_SUCCESS IS 1;
17
18    TYPES
19       FileRec IS RECORD
20          LineNbr:Integer;
21          Buff:String;
22          END; 
23
24    ROUTINES 
25
26    FUNCTION RcvData(REF w:WINDOW, VAL Conv:
                      Conversation):INTEGER IS
27    VARIABLES
28       totalBuff :FileRec;
29       dataRcvd :integer;
30       statRcvd :integer;
31       reqTSRcvd :integer;
32       rc :integer;
33    ACTIONS
34       IF (not(Known(w))) THEN
35          WinCreateScrollWindow($DESKTOP,w,
36                                $NullHandler,
37                                1,1,67,7,
                                  'FileSnd2','', 0,
                                  $WinBorder+
                                  $WinTitle+
                                  $WinHScroll+
                                  $WinVScroll+
38                                $WinSysMenu+
                                  $WinResize);
39       END;
40       REPEAT
41          rc := CPICReceive(Conv,'FILEREC.DDF',
                              totalBuff,DataRcvd,
                              StatRcvd,ReqTSRcvd);
42          IF (rc > 0) THEN
43          IF ((StatRcvd = $CPICConfirmReceived)or 
44             (StatRcvd=$CPICConfirmSendReceived))
                 THEN
45              rc := CPICConfirmed(Conv);
46          END;
47          totalBuff.buff := StrTrim
                (totalBuff.buff);
48          WinWriteLn(w,totalBuff.lineNbr:5&':
                       '&totalBuff.buff);
49          END;
50       UNTIL ((rc <> 1) OR ((StatRcvd =
                         $CPICSendReceived) OR 
51                    StatRcvd=
                          $CPICConfirmSendReceived)));
52       Exit(rc);
53    END; -- RcvData
54
55
56    ---------------------------------------------
57    -- Description: Reads in the specified file,
         transmitting each line via CPIC
58    -- to the partner specified through the given
         SDN
59    ---------------------------------------------
60    PROCEDURE DoConversation(VAL Args:
                                   List of String) IS
61    VARIABLES
62       Conv :Conversation;
63       fRec :FileRec;
64       ReqTSRcvd :INTEGER;
65       rc :INTEGER;
66       inf :FILE;
67       w :WINDOW;
68       t1,t2 :TIME;
69    ACTIONS
70       t1 := $NOW;
71    IF (ListLength(Args) < 2) THEN
72    WinMessageBox($DESKTOP,'Oops',
                    $MBOK,'KML FILESND 
                    {SDN} {INFILE}');
73       Exit;
74    END; 
75
76    FOpen(inf,Args[2],$Read); 
77
78    rc := CPICInitialize(Conv,Args[1]);
79    IF (rc < CPIC_SUCCESS) THEN
80       WinMessageBox($DESKTOP,'CPIC Error',
                       $MBOK,'Init returns
                       '&rc);
81       Exit;
82    END;
83    rc := CPICSetSyncLevel(Conv, $CPICNone);
84    IF (rc < CPIC_SUCCESS) THEN
85       WinMessageBox($DESKTOP,'CPIC Error',
                       $MBOK,'SSL returns
                       '&rc);
86    END;
87    rc := CPICAllocate(Conv);
88    IF (rc < CPIC_SUCCESS) THEN
89       WinMessageBox($DESKTOP,'CPIC Error',
                       $MBOK,'Allc returns
                       '&rc);
90       Exit;
91    END; 
92    rc := CPICSetPrepareToReceiveType(Conv,
93                                     $CPICPrep
                                       ToReceiveFlush); 
94    IF (rc < CPIC_SUCCESS) THEN
95       WinMessageBox($DESKTOP,'CPIC Error',
                       $MBOK,'SPTR returns
                       '&rc);
96    END; 
97
98    fRec.lineNbr := 0;
99    while (FReadLn(inf,fRec.Buff) > 0) do
100(* NEW *)
101-- By knowing if you are at the end of the
       file, you can set the appropriate 
102-- send type. This allows you to avoid
       calling CPICPrepareToReceive later
103-- and it avoids making the node services
       system do an extra transmission
104-- to the partner.
105   IF (FEnd(inf)) THEN
106     CPICSetSendType(Conv,
                        $CPICSendAndPrep
                        ToReceive);
      END;
107   (* END NEW *)
108        fRec.Buff := fRec.Buff & Char(13) &
                           Char(10);
             -- add CR LF
109         fRec.lineNbr := fRec.lineNbr + 1;
110         rc := CPICSend(Conv,
                           'FILEREC.DDF',
                           fRec,
                           ReqTSRcvd); 
111         IF (rc < CPIC_SUCCESS) THEN
112           WinMessageBox($DESKTOP,'CPIC Error',
                           $MBOK,'Send returns
                           '&rc);
         ExitLoop;
113   END;
114-- Let CM/2 do buffering. The other end will
       still see the 
115-- same number of sent buffers. CM/2 may
       batch some 
116-- of the buffers for efficiency
117    (* CPICFlush(Conv); *) 
118
119   END;
120   FClose(inf); 
121
122   IF (rc = CPIC_SUCCESS) THEN
123-- Don't have to do this, because this
       notification sent along with last send.
124   CPICPrepareToReceive(Conv);
   -- Indicates Partner may send now. --
125     t2 := $NOW;
126     RcvData(w,Conv);
127   END;
128
129   CPICDeallocate(Conv);
130   WinWriteLn(w,'<<<<<<<<<<<<<<<<<<<<<<<<
                    >>>>>>>>>>>>>>>>>>');
131   WinWriteLn(w,'Elapsed time 
                for outgoing transmission: '&
                TimeDif(t2,t1,$SECONDS)&'
                seconds');
      WinWait(w);
132END;

Summary of changes to improve performance

As you can see, it did not take much effort to make this application run faster. Lines 105-108 were added and lines 117 and 124 removed (commented out).

The changes implemented in FILESND2.KB are:

There are drawbacks to using the data buffering of CPIC. The main problem is that your application is not "in contact" as frequently with the partner application. In the case of this example, this does not matter. However, there are many cases where partner applications need to be able to request the right to send dynamically. In these cases, it is best that you control the flushing of the buffer in order to receive flags from the partner application as often as possible.


Tivoli Service Desk 6.0 Developer's Toolkit Legacy APIs Guide

Back to Table of Contents

Copyright